
/*****************backbone 模型******************/

var CollectionList = Backbone.Collection.extend({
	model:function(attrs){
		if(attrs.source=='PC'){
			if(attrs.type=='video'){
				attrs.isVideo=true;
				attrs.poster=attrs.asset_meta_data.poster_image || attrs.photo_url+'?vframe/jpg/offset/1';
			}
			attrs.ratio=attrs.asset_meta_data && !attrs.ratio?attrs.asset_meta_data.ratio:attrs.ratio
		}
		if(!($(window).width()<768 && !isTV()) && attrs.type!='video'){
			attrs.photo_url=attrs.photo_url+(attrs.photo_url.indexOf('imageMogr/auto-orient')>=0?'':'?imageMogr/auto-orient')
		}
		if(attrs.user){
			attrs.user.profile_image=attrs.user.profile_image || '/dashboard/images/default_profile_image.png'
		}
		return new Backbone.Model(attrs)
	}
});

/*****************react mixins******************/
/*多图瀑布流继承此类*/
var WaterFaller=function(){
	return {
		//new function
		minWidth:250,
		minHeight:250,
		serial:false,
		lastLimitSizeWidth:1,
		getContentWidth:function(){
			var content=this.refs.main || this.refs.giant_screen;

			return $(content).width()
		},
		getContentHeight:function(){
			var content=this.refs.main || this.refs.giant_screen;

			return $(content).height()
		},
		getColNum:function(){
			var contentWidth=this.getContentWidth(),
				minWidth=this.minWidth;

			return !this.props.isPhone?Math.round(contentWidth/minWidth):1
		},
		getRowNum:function(){
			var contentHeight=this.getContentHeight(),
				minHeight=this.minHeight;

			return Math.ceil(contentHeight/minHeight)
		},
		getMaximumCol:function(){
			var colNum=this.getColNum();

			return colNum<4?1:2 //colNum>=4 && colNum<7?2:3
		},
		getMaximumRow:function(){
			var rowNum=this.getRowNum();

			return rowNum-1
		},
		getAverageWidth:function(list){
			var total=0,
				len=list.length;

			list.forEach(function(i,index){
				total+=i.width || 0
			});

			return parseInt(total/len);
		},
		getAverageHeight:function(){
			var listArray=(this.state?this.state.listArray:null) || this.props.collection.toJSON(),
				total=0;

			listArray.forEach(function(i){
				total+=i.height || 0
			});

			return parseInt(total/listArray.length);
		},
		
		getItemFinalSize:function(real,avg,max){
			return Math.min(Math.ceil(real/(avg*2/max)),max)
		},
		getLimitSizeArr:function(list){
			var self=this,
				avgWidth=this.getAverageWidth(list),
				maxItemCol=this.getMaximumCol();
			 
			return list.map(function(model,index){
				if(model.ratio){
					var itemCol=self.getItemFinalSize(model.width,avgWidth,maxItemCol) || 1,
						itemRow=Math.round(model.ratio*itemCol) || 1;

					return _.extend(model,{
						col:itemCol,
						row:itemRow,
						index:index
					})
				}
			})
		},
		getLayout:function(isAnimation){
			var self=this,
				state=this.state,
				layout=state ? state.listArray : [],
				isAuditing=this.props.isAuditing,
				wallMode=isAuditing?'waterfall-with-text':this.props.wallMode,
				collection=this.props.collection,
				listArray=_.clone(collection.toJSON()),
				colNum=this.getColNum(),
				tempArr=_.clone(this.placeholder),
				minWidth=this.minWidth,
				minHeight=this.minHeight,
				//limitSizeArrOrigin=wallMode=='waterfall-of-grid'?this.getLimitSizeArr(listArray):null,
				//limitSizeArr=this.limitSizeArr,
				maxItemCol=wallMode=='waterfall-of-grid'?this.getMaximumCol():null;
			
			if(isAnimation){
				var screenHeight=document.body.offsetHeight,
					layoutHeight=tempArr.length?_.min(tempArr):0,
					collectionIndex=collection.indexOf(collection.get(this.lastItemCID)),
					targetHeight=Infinity,
					alreadyHasTemp=false;

				collectionIndex=collectionIndex>=0?collectionIndex:0;
				
				while(layoutHeight<targetHeight){
					if(!alreadyHasTemp && (layoutHeight>=screenHeight)){
						this.len=_.clone(layout).length;
						this.placeholderTemp=_.clone(tempArr);
						targetHeight=_.max(tempArr)+65+screenHeight,
						alreadyHasTemp=true
					}

					getItemLayout(listArray[collectionIndex],collectionIndex);

					layoutHeight=alreadyHasTemp?_.min(tempArr):_.max(tempArr)+65;
					collectionIndex<listArray.length-1?collectionIndex++:collectionIndex=0
				}
				
				this.lastItemCID=collection.at(collectionIndex).toJSON().cid
			}else{
				this.serial=false;
				listArray.forEach(function(model,index){
					getItemLayout(model,index)
				})
			}

			function getItemLayout(model,index){
				var position={},
					col=Math.min(tempArr.length!=colNum?tempArr.length:_.indexOf(tempArr,_.min(tempArr)),colNum-1),
					t=tempArr[col] || 0;
				
				if(colNum>1){
					switch(wallMode){
						case 'waterfall-with-text':
							if(model.h){
								position={
									w:minWidth,
									h:model.h,
									l:col*minWidth,
									t:t
								}
								
								tempArr[col]=t+model.h
							}
							break;
						case 'waterfall-without-text':
						case 'waterfall-of-grid':
							if(model.ratio){
								if(wallMode=='waterfall-without-text'){
									position={
										w:minWidth,
										h:model.ratio*minWidth,
										l:col*minWidth,
										t:t
									}
									tempArr[col]=t+model.ratio*minWidth
								}else{
									var expectWidth=Math.min(colNum-col,maxItemCol),
										gap=(function(g){
											for(var i=1;i<g;i++){
												if((tempArr[col+i] || 0) != t){
													return i
												}
											}
											return g
										})(expectWidth),
										hasSpace=gap==2, //&& Math.random()*100<=45
										lastOne=layout[index-1] || {},
										serialLeft=_.find(layout,function(i){
											return (i.t==t) && ((i.l+i.w)==col*minWidth) && i.w/minWidth==2
										}),
										notSerial=hasSpace && !serialLeft && !_.filter(layout,function(i){
											return (i.l/minWidth==col) && ((i.t+i.h)==t) && i.w/minWidth==2
										}).length,
										w=notSerial?2:1,
										itemWidth=w*minWidth,
										h=itemWidth*model.ratio,
										itemHeight=h+(parseInt(minWidth/6)-h%parseInt(minWidth/6));
									
									position={
										w:itemWidth,
										h:itemHeight,
										l:col*minWidth,
										t:t
									}
									
									for(var j=0;j<w;j++){
										tempArr[col+j]=(tempArr[col+j] || 0)+itemHeight
									}
								}
							}
							break;
						case 'dancing-pearl':
						case 'dancing-gem':
							position={
								l:index%colNum*minWidth+10,
								t:parseInt(index/colNum)*minWidth+10
							};
							break;

					}
				}

				if(position.timestamp){
					model=_.find(listArray,function(i){
						return i.timestamp==position.timestamp
					});
				}
				position=_.extend(_.clone(model),position);
				layout.push(position)
			}

			if(colNum>1 && (wallMode=='dancing-pearl' || wallMode=='dancing-gem')){
				tempArr=[Math.ceil(listArray.length/colNum)*minWidth]
			}

			this.tempArr=tempArr;
			//this.limitSizeArr=limitSizeArr;

			return layout
		},
		//old function
		tempArr:[],
		placeholder:[],
		placeholderTemp:[],
		len:0,
		animationStart:function(){
			var self=this,
				windowHeight=$(window).height(),
				listArray=this.state.listArray,
				tempArr=_.clone(this.tempArr),
				//min=_.min(tempArr)-100,
				//screenSize=Math.ceil(windowHeight/min),
				collection=this.props.collection.toJSON(),
				wallSpeed=this.props.wallSpeedList[this.props.wallSpeed].val,
				state={},
				layout=this.getLayout(true);

			state.listArray=layout;

			//this.placeholderTemp=tempArr;
			var max=_.max(this.placeholderTemp)+65,
				duration=max/wallSpeed*50;

			this.setAnimationStyle(duration/1000,function(){
				self.scrollTo(-max,function(){
					self.timer=setTimeout(function(){
						self.animationNext()
					},duration)
				})
			},state)
		},
		animationNext:function(){
			var self=this,
				listArray=this.state.listArray,
				tempArr=_.clone(this.tempArr),
				placeholderTemp=_.clone(this.placeholderTemp),
				max=_.max(placeholderTemp)+65,
				state={};

			this.placeholder=tempArr.map(function(i,index){
				return i-max
			});

			listArray.splice(0,this.len);

			listArray=listArray.map(function(i,index){
				i.t=i.t-max;
				return i
			});

			//this.len=_.clone(listArray).length;

			state.listArray=listArray;

			this.setAnimationStyle(0,function(){
				self.scrollTo(0,function(){
					self.animationStart()
				})
			},state)
		},
		getNewPage:function(height){
			var collection=this.props.collection,
				collectionArr=collection.toJSON(),
				len=collection.length,
				lastItemId=this.lastItemId,
				lastItemIndex=lastItemId?_.findIndex(collectionArr,function(i){ return i.id==lastItemId}):0,
				result=[];

			while(number>0){
				var targetIndex=_.min([lastItemIndex+number,len]);
				result=result.concat(collectionArr.slice(lastItemIndex,targetIndex));
				number=number-(targetIndex-lastItemIndex);
				lastItemIndex=targetIndex==len?0:targetIndex
			}
			this.lastItemId=collection.at(lastItemIndex).get('id');

			return result
		},
		scrollTo:function(distance,callback){
			this.setState({
				mainTop:distance
			},callback)
		},
		setAnimationStyle:function(duration,callback,state){
			state.tranStyle=duration?{
				'transition':'all '+duration+'s linear',
			    'OTransition':'all '+duration+'s linear',
			    'MsTransition':'all '+duration+'s linear',
			    'MozTransition':'all '+duration+'s linear',
			    'WebkitTransition':'all '+duration+'s linear'
			}:{};

			this.setState(state,callback)
		}
	}
};

/*多图卡片继承此类*/
var ListItemMixin=function(){
	return {
		refresh:function(){
			var model=_.clone(this.props.model);

			this.timer=setTimeout(function(){
				if(ReactDOM.findDOMNode()){
					this.setState({
						time:(function(){try{return moment(model.timestamp).fromNow()}catch(err){ return '1分钟内'}})()
					});
					this.refresh()
				}
			}.bind(this),60000);
		},
		componentWillUnmount:function(){
			clearTimeout(this.timer)
		},
		like:function(){
			var self=this,
				model=this.props.model,
				id=model.id,
				isLiking=this.state.isLiking,
				is_liked=this.state.is_liked;
			
			if(!isLiking){
				this.setState({
					isLiking:true
				});

				var  action = is_liked?'unlike':'like';

				//追踪点赞事件
				//fa('send','click',action);

				$.ajax({
					type:'post',
					url:'/walls/'+wallId+'/photos/'+id+'/'+action,
					dataType:'json',
					success:function(data){
						if(data.success){
							self.setState({
								likes:data.data,
								is_liked:!is_liked,
								isLiking:false,
								showLikeAnimation:true
							})
						}
					}
				})
			}
		},
		handle:function(method){
			var app=this.props.app,
				model=this.props.model,
				id=model.id,
				status=this.props.status=='approved'?'main':this.props.status;

			$.ajax({
				type:'post',
				url:'/walls/'+wallId+'/photos/'+id+'/'+method,
				dataType:'json',
				success:function(data){
					console.log(data);
					console.log(id);
					if(data.success && data.data){
						switch(method){
							case 'approve':
								var m=app.removeModel(status+'Collection',id);
								break;
							case 'reject':
								var m=app.removeModel(status+'Collection',id);
								break;
							case 'delete':
								var m=app.removeModel(status+'Collection',id);
								break;
						}
						
					}
				}
			})
		}
	}
};

/*****************react 模块******************/
/*图片墙*/
var MainList = React.createClass({
	mixins:[WaterFaller()],
	layoutCache:[],
	wallModeCache:null,
	componentWillMount:function(){
		var self=this,
			app=this.props.app,
			timer=null;
			
		$(window).unbind('resize').bind('resize',function(){
			if(timer){clearTimeout(timer)}

			timer=setTimeout(function(){
				var isPhone=$(window).width()<768;

				app.react.setState({
					isPhone:isPhone
				},function(){
					self.forceUpdate();
					console.log('resize');
					timer=null
				})
				self.isloaded=false
			},500)
		})
	},
	componentWillUpdate:function(){
		var isPhone=this.props.isPhone,
			wallMode=this.props.wallMode;

		if(!isPhone && wallMode!=this.wallModeCache){
			this.layoutCache=[];
			this.wallModeCache=wallMode
		}
	},
	componentWillUnmount:function(){
		$(window).unbind('resize')
	},
	render:function(){
		var app=this.props.app,
			isAuditing=this.props.isAuditing,
			message=this.props.message,
			isPhone=this.props.isPhone,
			wallMode=isPhone?'waterfall-with-text':this.props.wallMode,
			wallBackground=this.props.wallBackground,
			wallColor=this.props.wallColor,
			collection=this.props.collection,
			len=collection.length,
			listHtml=[],
			layout=this.layoutCache.length!=len?this.getLayout():this.layoutCache,
			className='main',
			status=this.props.status || 'pending';

		className+=wallMode=='waterfall-of-grid'?' main-sizelimit':'';

		collection.forEach(function(i,index){
			var model=i.toJSON();

			switch (wallMode){
				case 'waterfall-with-text':
					listHtml.push(<MainListItem key={model.id} isPhone={isPhone} position={layout[index]} app={app} model={model} backboneModel={i} index={index} wallColor={wallColor} isAuditing={isAuditing} status={status} />);
					break;
				case 'waterfall-without-text':
				case 'waterfall-of-grid':
					listHtml.push(<MainListPicItem key={layout[index].id} isPhone={isPhone} position={layout[index]} model={layout[index]} backboneModel={collection.get(layout[index].id)} index={index} wallColor={wallColor} />);
					break;
				case 'dancing-pearl':
				case 'dancing-gem':
					listHtml.push(<MainListGemItem key={model.id} isPhone={isPhone} position={layout[index]} model={model} index={index} wallColor={wallColor} wallMode={wallMode} />);
					break;
			}
		});

		this.layoutCache=layout;

		return (
			<div className={className}>
				{isAuditing?<ul className="nav nav-tabs pull-left navStyle navStyle-admin">
					<li className={"navStyleLi "+(status=='pending'?'navStyleLi-active':'')}><a className="liAStyle" href="#auditing/pending"><i className="glyphicon glyphicon-time"></i><b>{i18next.t('moderate.pending')}</b></a></li>
					<li className={"navStyleLi "+(status=='approved'?'navStyleLi-active':'')}><a className="liAStyle" href="#auditing/approved"><i className="glyphicon glyphicon-ok"></i> <b>{i18next.t('moderate.approve')}</b></a></li>
					<li className={"navStyleLi "+(status=='rejected'?'navStyleLi-active':'')}><a className="liAStyle" href="#auditing/rejected"><i className="glyphicon glyphicon-remove"> </i><b>{i18next.t('moderate.reject')}</b></a></li>
					<li className={"navStyleLi "+(status=='deleted'?'navStyleLi-active':'')}><a className="liAStyle" href="#auditing/deleted"><i className="glyphicon glyphicon-trash"></i> <b>{i18next.t('moderate.trash')}</b></a></li>
				</ul>:''}
				<div id="main" ref="main" style={{height:_.max(this.tempArr) || 'auto',marginTop:isAuditing?'38px':null}}>
					{<center className="hd top-hd" style={{marginBottom:'10px'}}><a href="http://www.parllay.cn/billboards/" style={{color:'#fff'}} target="_blank">{message?message:isAuditing&&!len? i18next.t('moderate.nopending_picture'): i18next.t('home.proered_by_parllay')}</a></center>}
					{listHtml}
				</div>
				{isPhone?<Toolbar />:null}
			</div>
		)
	}
});

/*社区版无照片引导页面*/
class MainGuide extends React.Component {
	render (){
		return (
			<div className="main main-guide">
				<a href="#photo" className="main-guide-inner">
					<p><i className="glyphicon glyphicon-camera"></i></p>
					<p>{i18next.t('home.click_upload')}</p>
					<p>{i18next.t('home.material_management')}</p>
				</a>
			</div>
		)
	}
}

var MainListItem = React.createClass({
	mixins:[ListItemMixin()],
	getInitialState:function(){
		var model=_.clone(this.props.model);

		this.refresh();

		return {
			time:(function(){try{return moment(model.timestamp).fromNow()}catch(err){ return '1分钟内'}})(),
			isLiking:false,
			is_liked:model.is_liked,
			likes:model.likes,
			comments:model.comments_count || 0,
			isShowComment:false,
			showLikeAnimation:false
		}
	},
	shouldComponentUpdate:function(nextProps, nextState){
		return JSON.stringify(this.props.position)!=JSON.stringify(nextProps.position) || !this.props.isAnimating
	},
	componentDidMount:function(){
		this.componentDidUpdate()
	},
	componentDidUpdate:function(){
		var model=this.props.model;

		if(!model.h && model.ratio){
			this.loaded(model.ratio)
		}
	},
	loaded:function(e){
		var self=this,
			model=this.props.model,
			backboneModel=this.props.backboneModel,
			ele=$(this.refs.item),
			ratio=(typeof e=='object')?(e.target.height/e.target.width).toFixed(2):e,
			isPhone=this.props.isPhone;

		if((!model.width || !model.height) && !isPhone){
			if(!this.ajax){
				this.ajax=$.ajax({
					url:(model.isVideo?model.poster:model.photo_url).split('?')[0]+'?imageInfo',
					dataType:'json',
					success:function(info){
						if(info){
							backboneModel.set({
								width:info.width,
								height:info.height
							})
						}
						self.ajax=null
					},
					error:function(){
						self.ajax=null
					}
				})
			}
		}

		backboneModel.set({
			h:!isPhone?ele.outerHeight(true):null,
			ratio:ratio
		})	
		
	},
	openActionSheet:function(){
		var model=this.props.model;

		this.props.app.react.setState({
			actionSheet:{
				list:model.additional_url?[{
					name:'详情',
					href:model.additional_url
				}]:[]
			}
		})
	},
	showComment:function(){
		this.setState({
			isShowComment:!this.state.isShowComment
		})
	},
	clickTimer:0,
	doubleClick:function(){
		var self=this;
		this.clickTimer++;

        this.dbClickTimer=setTimeout(function () {
            self.clickTimer = 0
        }, 500);
        if (self.clickTimer > 1) {
            self.like();
            self.clickTimer = 0
        }
	},
	resetDbClick:function(){
		clearTimeout(this.dbClickTimer)
		this.clickTimer=0
	},
	render:function(){
		var app=this.props.app,
			model=this.props.model,
			index=this.props.index,
			wallColor=this.props.wallColor,
			isAuditing=this.props.isAuditing,
			checked=this.state.checked,
			time=this.state.time,
			isLiking=this.state.isLiking,
			is_liked=this.state.is_liked,
			likes=this.state.likes,
			comments=this.state.comments,
			position=this.props.position,
			isPhone=this.props.isPhone,
			Plan=typeof plan!='undefined'?plan:null,
			allowLike=(Plan && Plan.features) ? Plan.features.allow_like : false,
			allowComment=(Plan && Plan.features) ? Plan.features.allow_comment : false,
			allowExternalLink=(Plan && Plan.features) ? Plan.features.allow_external_link : false,
			contentAudit=(Plan && Plan.features) ? Plan.features.content_audit : false,
			photoUrl=model.isVideo?model.poster:model.photo_url,
			bodyWidth=parseInt(document.body.clientWidth),
			waterMark='', //'&watermark/2/text/UEFSTExZ/fontsize/'+bodyWidth*2.5+'/font/5a6L5L2T/fill/d2hpdGU=/dissolve/50/gravity/SouthEast/dx/20/dy/20',
			param = photoUrl.indexOf('?')>0?('&imageView2/3/w/'+bodyWidth+waterMark):('?imageView2/3/w/'+bodyWidth+waterMark),
			status=this.props.status,
			showLikeAnimation=this.state.showLikeAnimation,
			sourceLogo=model.source!='PC'?'/images/icons/'+model.source+'.png':'';

		
		return (
			<div className={model.isVideo?"list_item col-xs-12 list_item_video":"list_item col-xs-12"} style={!isPhone?position?{'position':'absolute','left':position.l,'top':position.t}:{opacity:0}:{}} ref="item" onTouchStart={isPhone && allowLike && !isAuditing?this.doubleClick:null} onTouchMove={isPhone && allowLike && !isAuditing?this.resetDbClick:null}>
				<div className="panel panel-default">
					<div className="panel-heading">
						<img className="img-responsive" src={photoUrl+(isPhone?param:'')} onClick={this.preview} onLoad={!model.h?this.loaded:''} style={{width:'100%',height:model.ratio && !isPhone?model.ratio*236:null,backgroundColor:'#ccc'}} />
						{sourceLogo?<img className="source_logo" width="32" height="32" src={sourceLogo} />:null}
						{model.isVideo?<img className="video_icon" src="/images/icons/play.png" />:''}
					</div>
					<div className="panel-body" style={{color:wallColor}}>
						<p>{model.description}</p>
						<div className="media">
							<div href="javascript:void(0)" className="media-left"><img className="img-circle avatar" src={model.user.profile_image} /></div>
							<div className="media-body text-muted">{model.user.name}</div>
							<span className="media-right text-right" >
								<span className="create-time">{time}</span>
							</span>
						</div>
						{!isAuditing && isPhone?<div className="media media_auditing">
							<span className="media-left text-left text-muted"></span>
							<span className="media-right text-right text-muted tools" >
								{allowComment?<i className="glyphicon glyphicon-edit glyphiconMargin"  onClick={this.showComment}></i>:null}
								{allowComment?comments || 0:null}
								{allowLike?<i className={is_liked?"glyphicon glyphicon-heart liked":"glyphicon glyphicon-heart-empty"} onClick={this.like}></i>:null}
								{allowLike?likes || 0:null}
								{allowExternalLink && model.additional_url?<a href={model.additional_url} className="glyphicon glyphicon-new-window"></a>:null}
							</span>
						</div>:''}
						<span></span>
						{!isAuditing && isPhone && this.state.isShowComment && allowComment?<ConmmentThree app={app} card={this} photoId={model.id} />:''}
						{isAuditing && contentAudit?<div className="media media_auditing">
							{status!='deleted'?<div className="btn btn-xs btn-default pull-left" onClick={function(){this.handle('delete')}.bind(this)}><i className="glyphicon glyphicon-trash"></i></div>:''}
							{status!='approved'?<div className="btn btn-xs btn-success pull-right" onClick={function(){this.handle('approve')}.bind(this)}><i className="glyphicon glyphicon-ok"></i></div>:''}
							{status!='rejected'?<div className="btn btn-xs btn-danger pull-right" onClick={function(){this.handle('reject')}.bind(this)}><i className="glyphicon glyphicon-remove"></i></div>:''}
						</div>:''}
					</div>
				</div>
				{isPhone && allowLike && showLikeAnimation?<i className={"list_item_overlay glyphicon glyphicon-heart "+(is_liked?"fade-in":"fade-out")}></i>:null}
				{isPhone && index>1 && (index+1)%5==0?<p className="ad-space">- {i18next.t('home.proered_by_parllay')} -</p>:null}
			</div>
		)
	}
});

var MainListPicItem = React.createClass({
	mixins:[ListItemMixin()],
	getInitialState:function(){
		var model=_.clone(this.props.model);

		this.refresh();

		return {
			time:(function(){try{return moment(model.timestamp).fromNow()}catch(err){ return '1分钟内'}})(),
			isLiking:false,
			is_liked:model.is_liked,
			likes:model.likes
		}
	},
	shouldComponentUpdate:function(nextProps, nextState){
		return JSON.stringify(this.props.position)!=JSON.stringify(nextProps.position)
	},
	loaded:function(e){
		var backboneModel=this.props.backboneModel,
			ratio=(e.target.height/e.target.width).toFixed(2);

		backboneModel.set({
			ratio:ratio
		})
	},
	render:function(){
		var model=this.props.model,
			wallColor=this.props.wallColor,
			time=this.state.time,
			isLiking=this.state.isLiking,
			is_liked=this.state.is_liked,
			likes=this.state.likes,
			position=this.props.position,
			isPhone=this.props.isPhone,
			url=model.isVideo?model.poster:model.photo_url,
			className='list_item col-xs-12 list_item_nopadding'+(model.isVideo?' list_item_video':''),
			Plan=typeof plan!='undefined'?plan:null,
			allowLike=(Plan && Plan.features) ? Plan.features.allow_like : false,
			sourceLogo=model.source!='PC'?'/images/icons/'+model.source+'.png':'';

		return (
			<div className={className} style={!isPhone?position?{'position':'absolute','left':position.l,'top':position.t,'width':position.w,'height':position.h,backgroundImage:'url('+url+')'}:{opacity:0}:{}} ref="item">
				<div className="panel panel-default" style={{margin:0}}>
					{sourceLogo?<img className="source_logo" width="32" height="32" src={sourceLogo} />:null}
					{model.isVideo?<img className="video_icon" src="/images/icons/play.png" />:''}
					<div className="panel-body panel-body-absolute" style={{color:wallColor}}>
						<div className="media media-pic">
							<div href="javascript:void(0)" className="media-left"><img className="img-circle avatar" src={model.user.profile_image} /></div>
							<div className="media-body text-muted">{model.user.name}<br /><span className="create-time">{time}</span></div>
							{allowLike?<span className="media-right text-right like" >
								<i className="glyphicon glyphicon-heart"></i>{likes || 0}
							</span>:''}
						</div>
					</div>
				</div>
			</div>
		)
	}
});

class MainListGemItem extends React.Component {
	constructor (){
		super();

		this.classNames = {
			'dancing-pearl':{
				normal:'gem_itme',
				super:'gem_itme super_gem_itme'
			},
			'dancing-gem':{
				normal:'gem_itme gem_itme_block',
				super:'gem_itme gem_itme_block super_gem_itme'
			}
		}
	}
	componentDidMount (){
		var model=this.props.model;

		if(!model.ratio){
			var backboneModel=this.props.backboneModel,
				image=new Image();
			image.onLoad=function(){
				var ratio=(image.height/image.width).toFixed(2);

				backboneModel.set({
					ratio:ratio
				})
			}
			image.src=model.photo_url+'?imageView2/2/w/100'
		}
	}
	loaded (e){
		var backboneModel=this.props.backboneModel,
			ratio=(typeof e=='object')?(e.target.height/e.target.width).toFixed(2):e;

		backboneModel.set({
			ratio:ratio
		})
	}
	render (){
		var {model, wallMode, wallColor, position, isPhone} = this.props,
			classNames=this.classNames[wallMode],
			ratio=model.ratio || 1,
			animateStyle=model.animateStyle || {},
			style=_.extend({'position':'absolute','left':position.l,'top':position.t,'width':230,'height':230,'marginLeft':0,'marginTop':0},animateStyle),
			bg={'backgroundImage':'url('+(model.isVideo?model.poster:model.photo_url)+')'};

		return (
			<div className={animateStyle.transform=='scale(3)'?classNames.super:classNames.normal} style={style}>
				<div className={model.isVideo?'gem_itme_bg list_item_video':'gem_itme_bg'} style={bg}></div>
				<div className="gem_user_box">
					<div style={{backgroundColor:'#F26236'}}>
						<div className="gem_user_info">
							<h4>{model.description}</h4>
							<p>{model.user.name}</p>
						</div>
					</div>
				</div>
				<img className="gem_avatar" src={model.user.profile_image} />
				{model.isVideo?<img className="video_icon" src="/images/icons/play.png" />:''}
			</div>
		)
	}
};

/*主菜单*/
class Menu extends React.Component {
	constructor (){
		super();

		this.menu = [{
			name: i18next.t('navigation.home'),
			linkName:'home',
			picName:''
		},{
			name: i18next.t('navigation.upload'),
			linkName:'photo',
			picName:''
		},{
			name: i18next.t('navigation.moderate'),
			linkName:'auditing',
			picName:''
		},{
			name: i18next.t('navigation.profile'),
			linkName:'setting',
			picName:''
		}]
	}
	render () {
		var {app, router, logo, mainTitle, status, isPath} = this.props;

		return (
			<div className="menu">
				<PCMenu menu={this.menu} app={app} logo={logo} mainTitle={mainTitle} />
				{isPath?<RotateMenu menu={this.menu} app={app} router={router} status={status} />:<PhoneMenu menu={this.menu} app={app} router={router} status={status} />}
			</div>
		);
	}
};

class PCMenu extends React.Component {
	shouldComponentUpdate (nextProps, nextState){
		return false
	}
	render (){
		var {app, menu, logo, mainTitle} = this.props;

		return (
			<div className="navbar navbar-default navbar-fixed-top hidden-xs" id="PCMenu">
				<div className="container-fluid">
					<a href={'#'+menu[0].linkName} className="navbar-brand wall_logo">{logo?<img src={logo} />:(mainTitle || menu[0].name)}</a>
					<a href={'#mixture-setting'} className="navbar-brand glyphicon glyphicon-th-large pull-right" style={{top:0,lineHeight:'22px',marginRight:'20px'}}></a>
					<a href={'#slider-setting'} className="navbar-brand glyphicon glyphicon-facetime-video pull-right" style={{top:0,lineHeight:'22px',marginRight:'20px'}}></a>
					<a href={'#wall-setting'} className="navbar-brand glyphicon glyphicon-th pull-right" style={{top:0,lineHeight:'22px',marginRight:'22px'}}></a>
				</div>
			</div>
		)
	}
};

class PhoneMenu extends React.Component {
	render (){
		var {app, menu, router, status} = this.props,
			menuRouters=app.menuRouters,
			index=menuRouters[router]?menuRouters[router].index:-1;
			//console.log(router)
		return (
			<div className="navbar-fixed-bottom visible-xs">
				<div className="weui_tabbar">
			        <a href={'#'+menu[0].linkName} className={index==0?"weui_tabbar_item weui_bar_item_on":"weui_tabbar_item"}>
			            <div className="weui_tabbar_icon">
			                <img src={index==0?'/images/icons/home2.png':'/images/icons/home1.png'} width="24" height="24" />
			            </div>
			            <p className="weui_tabbar_label">{menu[0].name}</p>
			        </a>
			        {canUpload?<a href={'#'+menu[1].linkName} className={index==1?"weui_tabbar_item weui_bar_item_on":"weui_tabbar_item"}>
			            <div className="weui_tabbar_icon">
			                <img src={index==1?'/images/icons/upload2.png':'/images/icons/upload1.png'} width="24" height="24" />
			            </div>
			            <p className="weui_tabbar_label">{menu[1].name}</p>
			        </a>:''}
			        {app.isAdmin?<a href={'#'+menu[2].linkName+'/'+status} className={index==2?"weui_tabbar_item weui_bar_item_on":"weui_tabbar_item"}>
			            <div className="weui_tabbar_icon">
			                <img src={index==2?'/images/icons/audit2.png':'/images/icons/audit1.png'} width="24" height="24" />
			            </div>
			            <p className="weui_tabbar_label">{menu[2].name}</p>
			        </a>:''}
			        <a href={'#'+menu[3].linkName} className={index==3?"weui_tabbar_item weui_bar_item_on":"weui_tabbar_item"}>
					    <div className="weui_tabbar_icon">
					        <span className="glyphicon glyphicon-user" style={{fontSize:'24px'}}></span>
					    </div>
					    <p className="weui_tabbar_label">{menu[3].name}</p>
					</a>
			    </div>
			</div>	
		)
	}
};

/*rotate animate menu*/
class RotateMenu extends React.Component {
	constructor (){
		super();

		this.state = {
			isOpen:true
		}
	}
	fold (){
		var isOpen=this.state.isOpen;

		this.setState({
			isOpen:!isOpen
		})
	}
	close (){
		this.setState({
			isOpen:false
		})
	}
	render (){
		var {app, menu, router, status} = this.props,
			menuRouters=app.menuRouters,
			index=menuRouters[router]?menuRouters[router].index:-1,
			isOpen=this.state.isOpen;

		return (
			<div className="blooming-menu__container visible-xs">
				<div className="blooming-menu__main-container">
					<button className={"blooming-menu__main is-inactive"+(isOpen?' is-active':'')} onClick={this.fold.bind(this)}>
						<i className="blooming-menu__main-content glyphicon glyphicon-list"></i>
					</button>
				</div>
				<ul className="blooming-menu__items">
					<li className={"blooming-menu__item"+(isOpen?' is-active':'')}><div className="blooming-menu__item-btn-wrapper"><a href={'#'+menu[3].linkName} className="blooming-menu__item-btn glyphicon glyphicon-user" onClick={this.close.bind(this)}></a></div></li>
					{app.isAdmin?<li className={"blooming-menu__item"+(isOpen?' is-active':'')}><div className="blooming-menu__item-btn-wrapper"><a href={'#'+menu[2].linkName+'/'+status} className="blooming-menu__item-btn glyphicon glyphicon-check" onClick={this.close.bind(this)}></a></div></li>:null}
					{canUpload?<li className={"blooming-menu__item"+(isOpen?' is-active':'')}><div className="blooming-menu__item-btn-wrapper"><a href={'#'+menu[1].linkName} className="blooming-menu__item-btn glyphicon glyphicon-camera" onClick={this.close.bind(this)}></a></div></li>:null}
					<li className={"blooming-menu__item"+(isOpen?' is-active':'')}><div className="blooming-menu__item-btn-wrapper"><a href={'#'+menu[0].linkName} className="blooming-menu__item-btn glyphicon glyphicon-picture" onClick={this.close.bind(this)}></a></div></li>
				</ul>
			</div>
		)
	}
};

/*helping tools on the right*/
class Toolbar extends React.Component {
	constructor (){
		super();

		this.state = {
			marginTop:0
		}
	}
	componentDidMount (){
		var height=this.refs.toolbar.offsetHeight;

		this.setState({
			marginTop:-height/2
		})
	}
	refresh (){
		window.location.href = location.href.split('#')[0].split('?')[0]+'?time='+((new Date()).getTime());
	}
	backTop (){
		$('body').animate({scrollTop:0})
	}
	render (){
		var marginTop=this.state.marginTop;

		return (
			<div className="toolbar" style={{marginTop:marginTop}} ref="toolbar">
				<div onClick={this.refresh.bind(this)}>刷 新</div>
				<div onClick={this.backTop.bind(this)}>顶 部</div>
			</div>
		)
	}
};

/*上传图片*/
class UploadPhoto extends React.Component {
	constructor (){
		super();

		this.localId = null;
		this.state = {
			content:'',
			number:0,
			src:null,
			outlink:''
		}
	}
	takePhoto () {
		var self = this;
		if(isWxReady) {
			wx.chooseImage({
				count: 1, // 默认9
				sizeType: ['compressed'], // 可以指定是原图还是压缩图，默认二者都有original
				sourceType: ['camera','album'], // 可以指定来源是相册还是相机，默认二者都有
				success: function (res) {
					var localIds = res.localIds; // 返回选定照片的本地ID列表，localId可以作为img标签的src属性显示图片
					self.localId = localIds[0];
					self.setState({
						src:localIds[0]
					})
				}
			})
		}
	}
	saveImage () {
		var self=this,
			app=this.props.app,
			tempImg=$(this.refs.tempImg),
			w=parseInt(tempImg.width()),
			h=parseInt(tempImg.height()),
			content=$.trim(this.state.content),
			outlink=$.trim(this.state.outlink);

		if(!this.localId) {
			alert( i18next.t('upload.select_shooting'));
			return
		}

		if(outlink && !validateUrl(outlink)){
			alert('外部链接格式不合法');
			return
		}

		/*if(h>w*2){
			alert('您的图片太瘦啦，请换一张');
			return
		}*/
		wx.uploadImage({
			localId: this.localId,
			isShowProgressTips: 1,
			success: function(res) {
				var serverId = res.serverId;
				$('#toast2').show();
				setTimeout(function(){$('#toast2').hide()},3000);

				//追踪上传图片事件
				//fa('send','upload','photo');

				$.post('/wall/' + wallId + '/photos', {
					serverId: serverId,
					message: content,
					additional_url:outlink,
					ratio:(h/w).toFixed(2)
				}, function(data) {
					location.hash='home'
				})
			}
		})
	} 
	inputValue (e){
		var key=e.target.name,
			value=e.target.value,
			state={};

		switch(key){
			case 'content':
				state={
					content:value,
					number:value.length
				};
				break;
			case 'outlink':
				state={
					outlink:value
				};
				break;
		}

		this.setState(state)
	}
	scrollToSubmitBtn (e) {
		$('body').animate({scrollTop: e.target.height}, 1000)
	}
	render (){
		var {describe, qrCode} = this.props,
			{content, number, src, outlink} = this.state;
		
		if(window.__wxjs_is_wkwebview) {
			wx.getLocalImgData({
				localId: src,
				success: function (res) {
					src = res.localData
				}
			})
		}

		return (
			<div className="main main_setting">
				<center className="hd top-hd" style={{color:'#fff',marginBottom:'10px'}}>{i18next.t('home.proered_by_parllay')}</center>
				<div className="weui_cells weui_cells_form" style={{marginTop:'0',paddingBottom:'10px'}}>
					<div className="weui_cell">
			            <div className="weui_cell_bd weui_cell_primary">
			                <div className="weui_uploader">
			                    <div className="weui_uploader_hd weui_cell">
			                        <div className="weui_cell_bd weui_cell_primary">{i18next.t('upload.image_upload')}</div>
			                    </div>
			                    <div className="weui_uploader_bd upload_zone">
			                        <div className="weui_uploader_input_wrp"></div>
			                        <input className="weui_uploader_input" type="button" onClick={this.takePhoto.bind(this)} />
			                        {src?<img src={src} ref="tempImg" onLoad = {this.scrollToSubmitBtn} />:''}
			                    </div>
								{!src? <p className="weui_cells_tips text-center">请点击此区域上传图片（不支持webp格式）</p>: null}
			                </div>
			            </div>
			        </div>
			        <div className="weui_cell">
			            <div className="weui_cell_bd weui_cell_primary">
			                <textarea className="weui_textarea" name="content" placeholder=  {i18next.t('upload.comments')}  maxLength="140" rows="3" value={content} onChange={this.inputValue.bind(this)}></textarea>
			                <div className="weui_textarea_counter"><span>{number}</span>/140</div>
			            </div>
			        </div>
					<div className="weui_cell">
						<div className="weui_cell_bd weui_cell_primary">
							<input className="weui_input" type="url" name="outlink" placeholder="外部链接" value={outlink} onChange={this.inputValue.bind(this)} />
						</div>
					</div>
		        </div>
		        
		        <div className="weui_btn_area">
			        <div className="weui_btn weui_btn_primary" onClick={this.saveImage.bind(this)} id="showTooltips">{i18next.t('upload.submit')}</div>
			    </div>
			    <div className="weui_cells_tips" style={{marginTop:'10px'}}>{describe}</div>
			    <div className="weui_msg">
			    	{qrCode?<img className="wall_qrcode" src={qrCode} />:''}
			    </div>
			</div>
		)
	}
};

/*分屏方法集合*/
var mixtureControllers={
	'split-screen-1':{
		name:'左一右二',
		className:'fullscreen-multiply-three',
		screens:[
			{
				name: i18next.t('play_mode.more_screen_mode.tube'),
				type:'fullscreen',
				data:new CollectionList()
			},
			{
				name: i18next.t('play_mode.more_screen_mode.use'),
				type:'fullscreen',
				hasLogo:true,
				data:new CollectionList()
			},
			{
				name: i18next.t('play_mode.more_screen_mode.use'),
				type:'fullscreen',
				hasQrcode:true,
				data:new CollectionList()
			}
		],
		handler:function(collection){
			var screens=_.clone(this.screens);

			collection=_.filter(collection.toJSON(),function(i){
				if(i.source=='PC'){
					screens[0].data.add(i);
				}else{
					return true
				}
				return false
			});

			collection.forEach(function(i,index){
				var order=index%2+1;
				screens[order].data.add(i)
			});

			return screens
		}
	},
	'split-screen-2':{
		name:'左一右二2',
		className:'fullscreen-multiply-three',
		screens:[
			{
				name: i18next.t('play_mode.more_screen_mode.use'),
				type:'fullscreen',
				data:new CollectionList()
			},
			{
				name: i18next.t('play_mode.more_screen_mode.tube'),
				type:'fullscreen',
				hasLogo:true,
				data:new CollectionList()
			},
			{
				name: i18next.t('play_mode.more_screen_mode.use'),
				type:'fullscreen',
				hasQrcode:true,
				data:new CollectionList()
			}
		],
		handler:function(collection){
			var screens=_.clone(this.screens);

			collection=_.filter(collection.toJSON(),function(i){
				if(i.source=='PC'){
					screens[1].data.add(i);
				}else{
					return true
				}
				return false
			});

			collection.forEach(function(i,index){
				var order=index%2;
				screens[!order?order:order+1].data.add(i)
			});

			return screens
		}
	},
	'split-screen-3':{
		name:'左一右二3',
		className:'fullscreen-multiply-three',
		screens:[
			{
				name: i18next.t('play_mode.more_screen_mode.use'),
				type:'fullscreen',
				data:new CollectionList()
			},
			{
				name: i18next.t('play_mode.more_screen_mode.use'),
				type:'fullscreen',
				hasLogo:true,
				data:new CollectionList()
			},
			{
				name: i18next.t('play_mode.more_screen_mode.tube'),
				type:'fullscreen',
				hasQrcode:true,
				data:new CollectionList()
			}
		],
		handler:function(collection){
			var screens=_.clone(this.screens);

			collection=_.filter(collection.toJSON(),function(i){
				if(i.source=='PC'){
					screens[2].data.add(i);
				}else{
					return true
				}
				return false
			});

			collection.forEach(function(i,index){
				var order=index%2;
				screens[order].data.add(i)
			});

			return screens
		}
	},
	'split-screen-4':{
		name:'左二右一',
		className:'fullscreen-multiply-three2',
		screens:[
			{
				name: i18next.t('play_mode.more_screen_mode.use'),
				type:'fullscreen',
				data:new CollectionList()
			},
			{
				name: i18next.t('play_mode.more_screen_mode.use'),
				type:'fullscreen',
				data:new CollectionList()
			},
			{
				name: i18next.t('play_mode.more_screen_mode.tube'),
				type:'fullscreen',
				hasLogo:true,
				hasQrcode:true,
				data:new CollectionList()
			}
		],
		handler:function(collection){
			var screens=_.clone(this.screens);

			collection=_.filter(collection.toJSON(),function(i){
				if(i.source=='PC'){
					screens[2].data.add(i);
				}else{
					return true
				}
				return false
			});

			collection.forEach(function(i,index){
				var order=index%2;
				screens[order].data.add(i)
			});

			return screens
		}
	},
	'split-screen-5':{
		name:'左二右一2',
		className:'fullscreen-multiply-three2',
		screens:[
			{
				name: i18next.t('play_mode.more_screen_mode.tube'),
				type:'fullscreen',
				data:new CollectionList()
			},
			{
				name: i18next.t('play_mode.more_screen_mode.use'),
				type:'fullscreen',
				data:new CollectionList()
			},
			{
				name: i18next.t('play_mode.more_screen_mode.use'),
				type:'fullscreen',
				hasLogo:true,
				hasQrcode:true,
				data:new CollectionList()
			}
		],
		handler:function(collection){
			var screens=_.clone(this.screens);

			collection=_.filter(collection.toJSON(),function(i){
				if(i.source=='PC'){
					screens[0].data.add(i);
				}else{
					return true
				}
				return false
			});

			collection.forEach(function(i,index){
				var order=index%2+1;
				screens[order].data.add(i)
			});

			return screens
		}
	},
	'split-screen-6':{
		name:'左二右一3',
		className:'fullscreen-multiply-three2',
		screens:[
			{
				name: i18next.t('play_mode.more_screen_mode.use'),
				type:'fullscreen',
				data:new CollectionList()
			},
			{
				name: i18next.t('play_mode.more_screen_mode.tube'),
				type:'fullscreen',
				data:new CollectionList()
			},
			{
				name: i18next.t('play_mode.more_screen_mode.use'),
				type:'fullscreen',
				hasLogo:true,
				hasQrcode:true,
				data:new CollectionList()
			}
		],
		handler:function(collection){
			var screens=_.clone(this.screens);

			collection=_.filter(collection.toJSON(),function(i){
				if(i.source=='PC'){
					screens[1].data.add(i);
				}else{
					return true
				}
				return false
			});

			collection.forEach(function(i,index){
				var order=index%2;
				screens[!order?order:order+1].data.add(i)
			});

			return screens
		}
	},
	'split-screen-7':{
		name:'上一下四',
		className:'fullscreen-multiply-five',
		screens:[
			{
				name: i18next.t('play_mode.more_screen_mode.tube'),
				type:'fullscreen',
				data:new CollectionList()
			},
			{
				name: i18next.t('play_mode.more_screen_mode.use'),
				type:'fullscreen',
				data:new CollectionList()
			},
			{
				name:i18next.t('play_mode.more_screen_mode.use'),
				type:'fullscreen',
				data:new CollectionList()
			},
			{
				name: i18next.t('play_mode.more_screen_mode.use'),
				type:'fullscreen',
				data:new CollectionList()
			},
			{
				name:i18next.t('play_mode.more_screen_mode.use'),
				type:'fullscreen',
				data:new CollectionList()
			}
		],
		handler:function(collection){
			var screens=_.clone(this.screens);

			collection=_.filter(collection.toJSON(),function(i){
				if(i.source=='PC'){
					screens[0].data.add(i);
				}else{
					return true
				}
				return false
			});

			collection.forEach(function(i,index){
				var order=index%4+1;
				screens[order].data.add(i)
			});

			return screens
		}
	},
	'split-screen-8':{
		name:'上一下四2',
		className:'fullscreen-multiply-five',
		screens:[
			{
				name: i18next.t('play_mode.more_screen_mode.use'),
				type:'fullscreen',
				data:new CollectionList()
			},
			{
				name: i18next.t('play_mode.more_screen_mode.tube'),
				type:'fullscreen',
				data:new CollectionList()
			},
			{
				name: i18next.t('play_mode.more_screen_mode.tube'),
				type:'fullscreen',
				data:new CollectionList()
			},
			{
				name: i18next.t('play_mode.more_screen_mode.tube'),
				type:'fullscreen',
				data:new CollectionList()
			},
			{
				name: i18next.t('play_mode.more_screen_mode.tube'),
				type:'fullscreen',
				data:new CollectionList()
			}
		],
		handler:function(collection){
			var screens=_.clone(this.screens);

			collection=_.filter(collection.toJSON(),function(i){
				if(i.source!='PC'){
					screens[0].data.add(i);
				}else{
					return true
				}
				return false
			});

			collection.forEach(function(i,index){
				var order=index%4+1;
				screens[order].data.add(i)
			});

			return screens
		}
	}
};

/*分屏播放*/
class MixturePlayer extends React.Component {
	render (){
		var {app, isPhone, collection, mixtureMode, mixtureBackground, mixtureColor, mixtureSpeed, sliderSpeedList, wallSpeedList} = this.props,
			controller=mixtureControllers[mixtureMode],
			screens=controller.handler(collection);
 
		return (
			<div className={"giant_screen mixture_screen "+controller.className}>
				{screens.map(function(screen,index){
					if(screen.data.length){
						switch(screen.type){
							case 'waterfall':
								return <WallPlayer key={index} app={app} isPhone={isPhone} collection={screen.data} wallMode={'waterfall-with-text'} wallBackground={mixtureBackground} wallColor={mixtureColor} wallSpeed={mixtureSpeed} wallSpeedList={wallSpeedList} hasLogo={screen.hasLogo} />;
							case 'pearls':
								return <GemPlayer key={index} app={app} isPhone={isPhone} collection={screen.data} wallMode={'dancing-pearl'} wallBackground={mixtureBackground} wallColor={mixtureColor} wallSpeed={mixtureSpeed} wallSpeedList={wallSpeedList} hasLogo={screen.hasLogo} />;
							case 'fullscreen':
								return <SliderPlayer key={index} app={app} collection={screen.data} sliderMode={'classic-slides'} sliderBackground={mixtureBackground} sliderColor={mixtureColor} sliderSpeed={mixtureSpeed} sliderSpeedList={sliderSpeedList} hasLogo={screen.hasLogo} hasQrcode={screen.hasQrcode} hasDesc={screen.hasDesc} />;
						}
					}else{
						return <div key={index}></div>
					}
				})}
			</div>
		)
	}
};

/*视频播放器*/
class VideoPlayer extends React.Component {
	videoLoaded (e){
		e.target.play()
	}
	render (){
		var {model, callback} = this.props;

		return (
			<video style={{backgroundColor:'#333'}} src={model.photo_url} autoPlay onCanPlay={this.videoLoaded.bind(this)} onEnded={callback} width="100%" height="100%"></video>
		)
	}
};

/*幻灯片*/
class SliderPlayer extends React.Component {
	constructor (){
		super();

		this.last = -1;
		this.dir = 0;
		this.state = {
			cur:0
		}
	}
	componentDidMount (){
		//this.componentDidUpdate()
	}
	shouldComponentUpdate (nextProps, nextState){
		return this.state.cur != nextState.cur
	}
	playNext (){
		var self=this,
			app=this.props.app,
			cur=this.state.cur,
			collection=this.props.collection,
			next=collection.at(cur+1);

		this.last=cur;
		this.setState({
			cur:next?cur+1:0
		});

		if(!next && cur==0){
			this.forceUpdate()
		}
	}
	close (){
		location.hash='#home';
		screenfull && screenfull.exit();
	}
	render (){
		var self=this,
			cur=this.state.cur,
			{collection, sliderMode, sliderBackground, hasLogo, hasQrcode, hasDesc} = this.props,
			model=collection.at(cur)?collection.at(cur).toJSON():null,
			last=collection.at(this.last)?collection.at(this.last).toJSON():null,
			sliderColor = this.props.sliderColor;

		return (
			<div className="giant_screen" onClick={this.close.bind(this)} style={{backgroundColor:sliderBackground}}>
				{model?(function(){
					switch(sliderMode){
						case 'left-and-right':
							switch(self.dir){
								case 0:
									self.dir=1;
									return <Effect1 model={model} sliderColor= {sliderColor} slider={self} hasLogo={hasLogo} />;
								case 1:
									self.dir=0;
									return <Effect2 model={model} sliderColor= {sliderColor} slider={self} hasLogo={hasLogo} />;
							}
							break;
						case 'classic-slides':
							return <Effect3 model={model} slider={self} sliderColor= {sliderColor} last={last} hasLogo={hasLogo} hasQrcode={hasQrcode} hasDesc={hasDesc} />;
						case 'big-ball':
							return <Effect4 model={model} slider={self} sliderColor= {sliderColor} last={last} cur={cur} />;
					}
					
				})():''}
			</div>
		)
	}
};

/*幻灯效果左*/
class Effect1 extends React.Component {
	constructor (){
		super();

		this.state = {
			animateStyle:{}
		}
	}
	componentDidMount (){
		var self=this,
			{slider, model} = this.props,
			ratio=model.ratio,
			w=$(this.refs.giant_screen_img).width(),
			h=$(this.refs.giant_screen_img).height(),
			sliderSpeedMin=slider.props.sliderSpeedList[slider.props.sliderSpeed].val/1000,
			sliderSpeed=sliderSpeedMin/500,
			animateStyle={
				backgroundImage:'url('+model.photo_url+')',
				transitionTimingFunction:'linear',
				MozTransitionTimingFunction:'linear',
				WebkitTransitionTimingFunction:'linear',
				OTransitionTimingFunction:'linear',
				MsTransitionTimingFunction:'linear'
			},
			imgWidth=w+'px',
			imgHeight=h+'px',
			transform='translate(0,0)',
			duration=sliderSpeedMin;
		
		if(!model.isVideo){
			if(ratio){
				if(ratio>h/w){
					imgHeight=w*ratio+'px';
					transform='translate(0,'+(h-w*ratio)+'px)';
					duration=_.max([(w*ratio-h)*sliderSpeed,duration])
				}else{
					imgWidth=h/ratio+'px';
					transform='translate('+(w-h/ratio)+'px,0)';
					duration=_.max([(h/ratio-w)*sliderSpeed,duration])
				}
			}

			setTimeout(function(){
				self.setState({
					animateStyle:{
						backgroundImage:'url('+model.photo_url+')',
						width:imgWidth,
						height:imgHeight
					}
				},function(){
					setTimeout(function(){
						self.setState({
							animateStyle:_.extend(animateStyle,{
								width:imgWidth,
								height:imgHeight,
								transform:transform,
								MozTransform:transform,
								WebkitTransform:transform,
								OTransform:transform,
								MsTransform:transform,
								transitionDuration:duration+'s',
								MozTransitionDuration:duration+'s',
								WebkitTransitionDuration:duration+'s',
								OTransitionDuration:duration+'s',
								MsTransitionDuration:duration+'s'
							})
						})
					},0)

					setTimeout(function(){
						slider.playNext()
					},duration*1000+1000)
				})
			})
		}
	}
	render (){
		var {slider, model, sliderColor, hasLogo} = this.props,
			animateStyle=this.state.animateStyle,
			Plan=typeof plan!='undefined'?plan:null,
			isHideLogo=(Plan && Plan.features) ? Plan.features.is_hide_parllay_logo : false,
			sourceLogo=model.source!='PC'?'/images/icons/'+model.source+'.png':'';

		return (
			<div className="row giant_screen_row" style={{color:sliderColor}}>
				<div className="col-sm-8 giant_screen_pic">
					<div ref="giant_screen_img">
						{!model.isVideo?<div style={animateStyle}></div>:<VideoPlayer model={model} callback={slider.playNext} />}
					</div>
				</div>
				<div className="col-sm-4 giant_screen_right">
					<h1 className="giant_screen_title">{model.description}</h1>
					<div className="media" >
						<div href="javascript:void(0)" className="media-left"><img className="img-circle avatar" src={model.user.profile_image} /></div>
						<h4 className="media-body text-muted">{model.user.name}<br /><span className="create-time">{moment(new Date(model.timestamp)).fromNow()}</span></h4>
						<h4 className="media-right text-right text-muted source_logo" >{sourceLogo?<img width="48" height="48" src={sourceLogo} />:null}</h4>
					</div>
				</div>
				{hasLogo?<img className="parllay_logo" src={!isHideLogo?"/dashboard/images/sign-in-logo.png":wallLogo} />:''}
			</div>
		)
	}
};

/*幻灯效果右*/
class Effect2 extends React.Component {
	constructor (){
		super();

		this.state = {
			animateStyle:{}
		}
	}
	componentDidMount (){
		var self=this,
			{slider, model} = this.props,
			ratio=model.ratio,
			w=$(this.refs.giant_screen_img).width(),
			h=$(this.refs.giant_screen_img).height(),
			sliderSpeedMin=slider.props.sliderSpeedList[slider.props.sliderSpeed].val/1000,
			sliderSpeed=sliderSpeedMin/500,
			animateStyle={
				backgroundImage:'url('+model.photo_url+')',
				transitionTimingFunction:'linear',
				MozTransitionTimingFunction:'linear',
				WebkitTransitionTimingFunction:'linear',
				OTransitionTimingFunction:'linear',
				MsTransitionTimingFunction:'linear'
			},
			imgWidth=w+'px',
			imgHeight=h+'px',
			transform='translate(0,0)',
			duration=sliderSpeedMin;
		
		if(!model.isVideo){
			if(ratio){
				if(ratio>h/w){
					imgHeight=w*ratio+'px';
					transform='translate(0,'+(h-w*ratio)+'px)';
					duration=_.max([(w*ratio-h)*sliderSpeed,duration])
				}else{
					imgWidth=h/ratio+'px';
					transform='translate('+(w-h/ratio)+'px,0)';
					duration=_.max([(h/ratio-w)*sliderSpeed,duration])
				}
			}

			setTimeout(function(){
				self.setState({
					animateStyle:{
						backgroundImage:'url('+model.photo_url+')',
						width:imgWidth,
						height:imgHeight
					}
				},function(){
					setTimeout(function(){
						self.setState({
							animateStyle:_.extend(animateStyle,{
								width:imgWidth,
								height:imgHeight,
								transform:transform,
								MozTransform:transform,
								WebkitTransform:transform,
								OTransform:transform,
								MsTransform:transform,
								transitionDuration:duration+'s',
								MozTransitionDuration:duration+'s',
								WebkitTransitionDuration:duration+'s',
								OTransitionDuration:duration+'s',
								MsTransitionDuration:duration+'s'
							})
						})
					},0)

					setTimeout(function(){
						slider.playNext()
					},duration*1000+1000)
				})
			})
		}
	}
	render (){
		var {slider, model, sliderColor, hasLogo} = this.props,
			animateStyle=this.state.animateStyle,
			Plan=typeof plan!='undefined'?plan:null,
			isHideLogo=(Plan && Plan.features) ? Plan.features.is_hide_parllay_logo : false,
			sourceLogo=model.source!='PC'?'/images/icons/'+model.source+'.png':'';

		return (
			<div className="row giant_screen_row" style={{color:sliderColor}}>
				<div className="col-sm-4 giant_screen_right giant_screen_left">
					<h1 className="giant_screen_title">{model.description}</h1>
					<div className="media">
						<div href="javascript:void(0)" className="media-left"><img className="img-circle avatar" src={model.user.profile_image} /></div>
						<h4 className="media-body text-muted">{model.user.name}<br /><span className="create-time">{moment(new Date(model.timestamp)).fromNow()}</span></h4>
						<h4 className="media-right text-right text-muted source_logo" >{sourceLogo?<img width="48" height="48" src={sourceLogo} />:null}</h4>
					</div>
				</div>
				<div className="col-sm-8 giant_screen_pic">
					<div ref="giant_screen_img">
						{!model.isVideo?<div style={animateStyle}></div>:<VideoPlayer model={model} callback={slider.playNext} />}
					</div>
				</div>
				{hasLogo?<img className="parllay_logo" src={!isHideLogo?"/dashboard/images/sign-in-logo.png":wallLogo} />:''}
			</div>
		)
	}
};

/*幻灯效果大屏*/
class Effect3 extends React.Component {
	constructor (){
		super();

		this.state = {
			animateStyle:{}
		}
	}
	componentDidMount (){
		this.componentWillReceiveProps(this.props)
	}
	componentWillReceiveProps (props){
		var self=this,
			{slider, model} = props,
			ratio=model.ratio,
			w=document.body.offsetWidth,
			h=document.body.offsetHeight,
			sliderSpeedMin=slider.props.sliderSpeedList[slider.props.sliderSpeed].val/1000,
			sliderSpeed=sliderSpeedMin/500,
			animateStyle={
				backgroundImage:'url('+model.photo_url+')',
				transitionTimingFunction:'linear',
				MozTransitionTimingFunction:'linear',
				WebkitTransitionTimingFunction:'linear',
				OTransitionTimingFunction:'linear',
				MsTransitionTimingFunction:'linear'
			},
			imgWidth=w,
			imgHeight=h,
			transform='translate(0,0)',
			duration=sliderSpeedMin;
		
		if(!model.isVideo){
			if(ratio){
				if(ratio>h/w){
					imgHeight=w*ratio;
					transform='translate(0,'+(h-w*ratio)+'px)';
					duration=_.max([(w*ratio-h)*sliderSpeed,duration])
				}else{
					imgWidth=h/ratio;
					transform='translate('+(w-h/ratio)+'px,0)';
					duration=_.max([(h/ratio-w)*sliderSpeed,duration])
				}
			}
			
			setTimeout(function(){
				self.setState({
					animateStyle:{
						backgroundImage:'url('+model.photo_url+')',
						width:imgWidth,
						height:imgHeight,
						backgroundPosition:'center'
					}
				},function(){
					setTimeout(function(){
						self.setState({
							animateStyle:_.extend(animateStyle,{
								width:imgWidth,
								height:imgHeight,
								transform:transform,
								MozTransform:transform,
								WebkitTransform:transform,
								OTransform:transform,
								MsTransform:transform,
								transitionDuration:duration+'s',
								MozTransitionDuration:duration+'s',
								WebkitTransitionDuration:duration+'s',
								OTransitionDuration:duration+'s',
								MsTransitionDuration:duration+'s'
							})
						})
					});
					
					self.timer=setTimeout(function(){
						self.setState({
							animateStyle:false
						},function(){
							self.playNext()
						})
					},duration*1000+1000)
				})
			})
		}
	}
	playNext (){
		var slider=this.props.slider;
		slider.playNext()
	}
	componentWillUnmount (){
		clearTimeout(this.timer)
	}
	render (){
		var {model, last, hasLogo, hasQrcode, hasDesc} = this.props,
			sliderColor=this.props.sliderColor,
			wallColor = this.props.wallColor,
			animateStyle=this.state.animateStyle,
			Plan=typeof plan!='undefined'?plan:null,
			isHideLogo=(Plan && Plan.features) ? Plan.features.is_hide_parllay_logo : false,
			sourceLogo=model.source!='PC'?'/images/icons/'+model.source+'.png':'',
			wrapperStyle={color:sliderColor};
		
		if(last && last.photo_url){
			var moveDir=last.ratio>(document.body.offsetHeight/document.body.offsetWidth);

			wrapperStyle=_.extend(wrapperStyle,{
				backgroundImage:'url('+last.photo_url+')',
				backgroundSize:moveDir?'100% auto':'auto 100%',
				backgroundPosition:moveDir?'bottom center':'center right'
			})
		}

		return (
			<div className="giant_screen_row full_background_screen" ref="giant_screen_img" style={wrapperStyle}>
				{!model.isVideo?animateStyle?<div>
					<div className="giant_screen_background" style={animateStyle} ></div>
					<div className="media" style={{color:sliderColor}}>
						<div href="javascript:void(0)" className="media-left"><img className="img-circle avatar" src={model.user.profile_image} /></div>
						<h4 className="media-body">{model.user.name}<br /><span className="create-time">{(function(){try{return moment(model.timestamp).fromNow()}catch(err){ return '1分钟内'}})()}</span></h4>
						<h4 className="media-right text-right text-muted source_logo" ></h4>
					</div>
					{hasDesc?<h1 className="giant_screen_title">{sourceLogo?<img width="48" height="48" src={sourceLogo} />:null}{model.description}</h1>:null}
					{hasLogo?<img className="parllay_logo" src={!isHideLogo?"/dashboard/images/sign-in-logo.png":wallLogo} />:null}
					{hasQrcode && wallQrcode?<img className="parllay_qrcode" src={wallQrcode} />:null}
					{hasQrcode && wallQrcode?<div className="follows_us"><p>扫描二维码</p><p>关注我们</p></div>:null}
				</div>:<div><div></div></div>:<VideoPlayer model={model} callback={() => this.playNext()} />}
			</div>
		)
	}
};

/*幻灯效果圆球*/
class Effect4 extends React.Component {
	constructor (props){
		super();

		this.colorList = ['#F26236','#60B2A5','#B2C036','#2f7ed8','#e05f6f'];
		this.animateStyle = {
			scale:{
				out:{
					transform:'scale(0)',
					MozTransform:'scale(0)',
					WebkitTransform:'scale(0)',
					OTransform:'scale(0)',
					MsTransform:'scale(0)'
				}
			},
			rotate:{
				out:{
					transform:'rotateY(90deg)',
					MozTransform:'rotateY(90deg)',
					WebkitTransform:'rotateY(90deg)',
					OTransform:'rotateY(90deg)',
					MsTransform:'rotateY(90deg)'
				}
			},
			slide:{
				in:[
					{
						transitionDuration:'0s',
						MozTransitionDuration:'0s',
						WebkitTransitionDuration:'0s',
						OTransitionDuration:'0s',
						MsTransitionDuration:'0s'
					},
					{
						transitionDuration:'0s',
						MozTransitionDuration:'0s',
						WebkitTransitionDuration:'0s',
						OTransitionDuration:'0s',
						MsTransitionDuration:'0s',
						visibility:'hidden'
					}
				],
				out:[
					{
						transform:'translate(0,-100%)',
						MozTransform:'translate(0,-100%)',
						WebkitTransform:'translate(0,-100%)',
						OTransform:'translate(0,-100%)',
						MsTransform:'translate(0,-100%)',
						transitionTimingFunction:'ease-in-out',
						MozTransitionTimingFunction:'ease-in-out',
						WebkitTransitionTimingFunction:'ease-in-out',
						OTransitionTimingFunction:'ease-in-out',
						MsTransitionTimingFunction:'ease-in-out'
					},
					{
						transform:'translate(0,-100%)',
						MozTransform:'translate(0,-100%)',
						WebkitTransform:'translate(0,-100%)',
						OTransform:'translate(0,-100%)',
						MsTransform:'translate(0,-100%)',
						transitionTimingFunction:'ease-in-out',
						MozTransitionTimingFunction:'ease-in-out',
						WebkitTransitionTimingFunction:'ease-in-out',
						OTransitionTimingFunction:'ease-in-out',
						MsTransitionTimingFunction:'ease-in-out',
						transitionDuration:'0.4s',
						MozTransitionDuration:'0.4s',
						WebkitTransitionDuration:'0.4s',
						OTransitionDuration:'0.4s',
						MsTransitionDuration:'0.4s'
					}
				]
			},
			fade:{
				out:{
					
				}
			},
			default:{
				transform:'none',
				MozTransform:'none',
				WebkitTransform:'none',
				OTransform:'none',
				MsTransform:'none'
			}
		};
		this.animateDuration = {
			transitionDuration:'0.5s',
			MozTransitionDuration:'0.5s',
			WebkitTransitionDuration:'0.5s',
			OTransitionDuration:'0.5s',
			MsTransitionDuration:'0.5s',
		};
		this.typeList = ['scale','rotate','slide','fade'];
		this.state = {
			model:props.model,
			bgColor:this.colorList[0],
			animateMode:'in',
			animateType:'default'
		}
	}
	componentDidMount (){
		this.componentWillReceiveProps(this.props)
	}
	componentWillReceiveProps (props){
		var self=this,
			slider=this.props.slider,
			cur=props.cur,
			colorList=this.colorList,
			len=cur%colorList.length,
			bg=colorList[len],
			lastBg=colorList[len?len-1:colorList.length-1],
			type=this.typeList[Math.floor(Math.random()*4)], //Math.floor(Math.random()*3)
			sliderSpeed=slider.props.sliderSpeedList[slider.props.sliderSpeed].val/1000;

		if(!this.state.model.isVideo){
			if(props.last){
				this.setState({
					animateMode:'out',
					animateType:type
				},function(){
					setTimeout(function(){
						self.setState({
							model:props.model,
							bgColor:bg,
							animateMode:'in',
							animateType:type
						})
					},500)
				})
			}else{
				this.setState({
					model:props.model,
					bgColor:bg,
					animateMode:'in',
					animateType:type
				})
			}

			setTimeout(function(){
				slider.playNext()
			},sliderSpeed*1000+1000)
		}else{
			setTimeout(function(){
				self.setState({
					model:props.model,
					bgColor:bg,
					animateMode:'in',
					animateType:type
				})
			},0)
		}
	}
	render (){
		var model=this.state.model || {user:{}},
			nextModel=this.props.model || {user:{}},
			slider=this.props.slider,
			bgColor=this.state.bgColor,
			cur=this.props.cur,
			colorList=this.colorList,
			len=cur%colorList.length,
			nextBg=colorList[len],
			type=this.state.animateType,
			duration=this.animateDuration,
			animate=this.animateStyle[type][this.state.animateMode] || this.animateStyle['default'],
			sliderColor=this.props.sliderColor;
		
		return (
			<div className="giant_screen_row atmosphere_screen">
				{animate instanceof Array?[<div key={1} className="atmosphere img-circle" style={_.extend({borderColor:bgColor},duration,animate[0])}>
					{!model.isVideo?<div className="atmosphere-photo" style={{backgroundImage:'url('+model.photo_url+')'}}></div>:<VideoPlayer model={model} callback={slider.playNext} />}
					<div className="atmosphere-userinfo" style={{backgroundColor:bgColor,color:sliderColor}}>
						<img src={model.user.profile_image} />
						<h4>{model.user.name}</h4>
						<h4 className="atmosphere_desc">{model.description}</h4>
					</div>
				</div>,<div key={2} className="atmosphere img-circle" style={_.extend({borderColor:bgColor},duration,animate[1])}>
					<div className="atmosphere-photo" style={{backgroundImage:'url('+nextModel.photo_url+')'}}></div>
					<div className="atmosphere-userinfo" style={{backgroundColor:nextBg,color:sliderColor}}>
						<img src={nextModel.user.profile_image} />
						<h4>{nextModel.user.name}</h4>
						<h4 className="atmosphere_desc">{nextModel.description}</h4>
					</div>
				</div>]:[<div key={1} className="atmosphere img-circle" style={_.extend({borderColor:bgColor},duration,animate)}>
					{!model.isVideo?<div className="atmosphere-photo" style={_.extend(type=='fade'?duration:{},{backgroundImage:'url('+model.photo_url+')'})}></div>:<VideoPlayer model={model} callback={slider.playNext} />}
					<div className="atmosphere-userinfo" style={{backgroundColor:bgColor,color:sliderColor}}>
						<img src={model.user.profile_image} />
						<h4>{model.user.name}</h4>
						<h4 className="atmosphere_desc">{model.description}</h4>
					</div>
				</div>,<div key={2} className="atmosphere img-circle" style={{visibility:'hidden'}}></div>]}
			</div>
		)
	}
};

/*瀑布流一屏*/
class LoadItemsWithoutSize extends React.Component {
	render (){
		var collection=this.props.collection.models;

		return (
			<div className="main" style={{'position':'fixed','left':'-9999px'}}>
				{collection.map(function(i,index){
					var model=i.toJSON();
					if(!model.ratio || !model.h){
						return <MainListItem key={model.id} model={model} backboneModel={i} index={index} />;
					}
				})}
			</div>
		)
	}
};

/*瀑布流滚动*/
var WallPlayer = React.createClass({
	mixins:[WaterFaller()],
	getInitialState:function(){

		return {
			listArray:[],
			mainTop:0,
			tranStyle:{}
		}
	},
	shouldComponentUpdate:function(nextProps, nextState){
		var state=this.state;
		return (state.mainTop!=nextState.mainTop)  //(state.listArray.length!=nextState.listArray.length) || (state.mainTop!=nextState.mainTop)
	},
	componentDidMount:function(){
		this.animationStart()
	},
	close:function(){
		clearTimeout(this.timer);
		this.timer=null;
		location.hash='#home';
		screenfull && screenfull.exit();
	},
	render:function(){
		var app=this.props.app,
			isAuditing=this.props.isAuditing,
			wallMode=isAuditing?'waterfall-with-text':this.props.wallMode,
			wallBackground=this.props.wallBackground,
			wallColor=this.props.wallColor,
			collection=this.props.collection,
			listArray=this.state.listArray,
			isPhone=this.props.isPhone,
			listHtml=[],
			mainTop=this.state.mainTop,
			transform='translate(0px,'+mainTop+'px)',
			tranStyle=this.state.tranStyle,
			hasLogo=this.props.hasLogo,
			hasQrcode = this.props.hasQrcode,
			//layout=this.getLayout(),
			className='main giant_screen',
			Plan=typeof plan!='undefined'?plan:null,
			isHideLogo=(Plan && Plan.features) ? Plan.features.is_hide_parllay_logo : false;

			className+=wallMode=='waterfall-of-grid'?' main-sizelimit':'';

			listArray.forEach(function(model,index){
				switch (wallMode){
					case 'waterfall-with-text':
						listHtml.push(<MainListItem isAnimating={true} key={model.id+index} isPhone={isPhone} position={model} app={app} model={model} backboneModel={collection.get(model.id)} index={index} wallColor={wallColor} isAuditing={isAuditing} />);
						break;
					case 'waterfall-without-text':
					case 'waterfall-of-grid':
						listHtml.push(<MainListPicItem key={model.id+index} isPhone={isPhone} position={model} model={model} backboneModel={collection.get(model.id)} index={index} wallColor={wallColor} />);
						break;
				}
			});	

		return (
			<div className={className} onClick={this.close} style={{backgroundColor:wallBackground}}>
				<div id="main" ref="giant_screen" style={_.extend({height:_.max(this.tempArr),transform:transform,'MozTransform':transform,'WebkitTransform':transform,'OTransform':transform,'MsTransform':transform},tranStyle)}>
					{listHtml}
				</div>
				{hasLogo?<img className="parllay_logo" src={!isHideLogo?"/dashboard/images/sign-in-logo.png":wallLogo} />:''}
				{wallMode == 'waterfall-with-text' && hasQrcode && wallQrcode?<img className="parllay_qrcode qrcode_bottom" src={wallQrcode} />:null}
				{wallMode == 'waterfall-with-text' && hasQrcode && wallQrcode?<div className="follows_us qrcode_bottom"><p>扫描二维码</p><p>关注我们</p></div>:null}
			</div>
		)
	}
});

/*宝石阵*/
class GemPlayer extends React.Component {
	constructor (){
		super();

		this.counter = 0;
		this.state = {
			listArray:[]
		}
	}
	componentDidMount (){
		this.animationStart()
	}
	animationStart (){
		var self=this,
			collection=this.props.collection.toJSON(),
			listArray=this.state.listArray,
			len=listArray.length,
			wallSpeed=this.props.wallSpeedList[this.props.wallSpeed].val,
			isPhone=this.props.isPhone,
			colNum=$('#main')&&!isPhone?Math.round($('#main').width()/250):1,
			rowNum=!isPhone?Math.ceil(($('body').height()-65)/250):1,
			screenMaxGemLength=colNum*(rowNum+1);

		console.log(colNum+' , '+rowNum)
		listArray=listArray.concat(this.getNewRow(screenMaxGemLength-len));

		this.highlightItem=null;
		
		this.setState({
			listArray:listArray
		},function(){

			switch(self.counter){
				case 3:
					listArray=self.highlight(listArray,colNum,rowNum);
					break;
				case 4:
					listArray=self.highlight(listArray,colNum,rowNum,true);
					break;
				default:
					listArray=self.normalMove(listArray,colNum);
					break
			}

			setTimeout(function(){
				self.setState({
					listArray:listArray
				},function(){
					if(this.highlightItem){
						self.timer=setTimeout(function(){
							self.animationNext(listArray,colNum)
						},8000/wallSpeed)
					}else{
						self.timer=setTimeout(function(){
							self.animationNext(listArray,colNum)
						},8000/wallSpeed)
					}
				});
				//$(self.refs.temp).text('totalJSHeapSize:'+performance.memory.totalJSHeapSize+' , '+'usedJSHeapSize:'+performance.memory.usedJSHeapSize+' , '+'jsHeapSizeLimit:'+performance.memory.jsHeapSizeLimit)
			},0)
			
		})

	}
	animationNext (listArray,colNum){
		if(this.counter<4){
			listArray.splice(0,colNum);

			listArray.map(function(i,index){
				i.animateStyle={};
				return i
			});

			this.setState({
				listArray:listArray
			},function(){
				this.animationStart()
			}.bind(this))
		}else{
			this.animationStart()
		}
	}
	getNewRow (number){
		var collection=this.props.collection,
			collectionArr=collection.toJSON(),
			len=collection.length,
			lastGemId=this.lastGemId,
			lastGemIndex=lastGemId?_.findIndex(collectionArr,function(i){ return i.id==lastGemId}):0,
			result=[];

		while(number>0){
			var targetIndex=_.min([lastGemIndex+number,len]);
			result=result.concat(collectionArr.slice(lastGemIndex,targetIndex));
			number=number-(targetIndex-lastGemIndex);
			lastGemIndex=targetIndex==len?0:targetIndex
		}
		this.lastGemId=collection.at(lastGemIndex).get('id');

		return result
	}
	highlight (listArray,colNum,rowNum,isShrink){
		var point=this.highlightPoint,
			x=isShrink?point.x:Math.round(1+(colNum-3>0?colNum-3:0)*Math.random()),
			y=isShrink?point.y:Math.round(1+(rowNum-4>0?rowNum-4:0)*Math.random()),
			fromPoint=[x*250+125,y*250+125],
			maxDistance=0;
		
		listArray.forEach(function(i,index){
			var itemX=index%colNum,
				itemY=parseInt(index/colNum);

			if(itemX==x || itemY==y){
				var itemCenter = this.getViewportCenter(itemX,itemY),
					distance = this.distance(itemCenter, fromPoint);

				if (distance > maxDistance) {
					maxDistance = distance;
				}
			}
		}.bind(this));

		listArray=_.map(listArray,function(i,index){
			var itemX=index%colNum,
				itemY=parseInt(index/colNum),
				i=_.clone(i);

			if((Math.abs(itemX-x)<2 && itemY-y==0) || Math.abs(itemY-y)<2 || (Math.abs(itemY-y)<rowNum && Math.abs(itemX-x)==0)){
				var itemCenter = this.getViewportCenter(itemX,itemY),
				  	distance = this.distance(itemCenter, fromPoint),
					scaledDistance = distance / maxDistance,
				 	duration = 3 * scaledDistance;
				if(itemX==x && itemY==y){
					if(!isShrink){this.highlightPoint={x:itemX,y:itemY}}
					this.highlightItem=i.id;

					i.animateStyle={
						transitionTimingFunction:'cubic-bezier(0.493, 0, 0.112, 1)',
						MozTransitionTimingFunction:'cubic-bezier(0.493, 0, 0.112, 1)',
						WebkitTransitionTimingFunction:'cubic-bezier(0.493, 0, 0.112, 1)',
						OTransitionTimingFunction:'cubic-bezier(0.493, 0, 0.112, 1)',
						MsTransitionTimingFunction:'cubic-bezier(0.493, 0, 0.112, 1)',
						width:230,
						height:230,
						transitionDuration:1+'s',
						MozTransitionDuration:1+'s',
						WebkitTransitionDuration:1+'s',
						OTransitionDuration:1+'s',
						MsTransitionDuration:1+'s',
						transitionProperty:'transform width height',
						MozTransitionProperty:'transform width height',
						WebkitTransitionProperty:'transform width height',
						OTransitionProperty:'transform width height',
						MsTransitionProperty:'transform width height',
						transform:!isShrink?'scale(3)':'scale(1)',
						MozTransform:!isShrink?'scale(3)':'scale(1)',
						WebkitTransform:!isShrink?'scale(3)':'scale(1)',
						OTransform:!isShrink?'scale(3)':'scale(1)',
						MsTransform:!isShrink?'scale(3)':'scale(1)',
						marginLeft:0,
						marginTop:0
					}
				}else{
					var offsetX=(itemX-x>0?1:itemX-x<0?-1:0)*250,
						offsetY=(offsetX?0:itemY-y>0?1:itemY-y<0?-1:0)*250;
					
					i.animateStyle={
						transitionTimingFunction:'cubic-bezier(0.493, 0, 0.112, 1)',
						MozTransitionTimingFunction:'cubic-bezier(0.493, 0, 0.112, 1)',
						WebkitTransitionTimingFunction:'cubic-bezier(0.493, 0, 0.112, 1)',
						OTransitionTimingFunction:'cubic-bezier(0.493, 0, 0.112, 1)',
						MsTransitionTimingFunction:'cubic-bezier(0.493, 0, 0.112, 1)',
						transitionDuration:duration+'s',
						MozTransitionDuration:duration+'s',
						WebkitTransitionDuration:duration+'s',
						OTransitionDuration:duration+'s',
						MsTransitionDuration:duration+'s',
						transitionProperty:'transform width height',
						MozTransitionProperty:'transform width height',
						WebkitTransitionProperty:'transform width height',
						OTransitionProperty:'transform width height',
						MsTransitionProperty:'transform width height',
						transform:'translate('+(isShrink?0:offsetX)+'px,'+(isShrink?0:offsetY)+'px)',
						MozTransform:'translate('+(isShrink?0:offsetX)+'px,'+(isShrink?0:offsetY)+'px)',
						WebkitTransform:'translate('+(isShrink?0:offsetX)+'px,'+(isShrink?0:offsetY)+'px)',
						OTransform:'translate('+(isShrink?0:offsetX)+'px,'+(isShrink?0:offsetY)+'px)',
						MsTransform:'translate('+(isShrink?0:offsetX)+'px,'+(isShrink?0:offsetY)+'px)',
						width:230,
						height:230,
						marginLeft:0,
						marginTop:0
					}
				}
			}else{
				i.animateStyle={
					transform:'translate(0px,0px)'
				}
			}

			return i
		}.bind(this));
		
		this.counter++;

		return listArray
	}
	normalMove (listArray,colNum){
		var container=this.refs.giant_gem_screen,
			fromPoint=[$(container).width() * Math.round(Math.random()), $(container).height() + 250 * 2.5],
			maxDistance=0;

		listArray.forEach(function(i,index){
			var itemCenter = this.getViewportCenter(index%colNum,parseInt(index/colNum)),
				distance = this.distance(itemCenter, fromPoint);

			if (distance > maxDistance) {
				maxDistance = distance;
			}
		}.bind(this));

		listArray=_.map(listArray,function(i,index){

			var itemCenter = this.getViewportCenter(index%colNum,parseInt(index/colNum)),
			  	distance = this.distance(itemCenter, fromPoint),
				scaledDistance = distance / maxDistance,
			 	duration = 3 * scaledDistance,
			 	i=_.clone(i);
			
			i.animateStyle={
				transitionTimingFunction:'cubic-bezier(0.493, 0, 0.112, 1)',
				MozTransitionTimingFunction:'cubic-bezier(0.493, 0, 0.112, 1)',
				WebkitTransitionTimingFunction:'cubic-bezier(0.493, 0, 0.112, 1)',
				OTransitionTimingFunction:'cubic-bezier(0.493, 0, 0.112, 1)',
				MsTransitionTimingFunction:'cubic-bezier(0.493, 0, 0.112, 1)',
				transitionDuration:duration+'s',
				MozTransitionDuration:duration+'s',
				WebkitTransitionDuration:duration+'s',
				OTransitionDuration:duration+'s',
				MsTransitionDuration:duration+'s',
				transitionProperty:'transform width height',
				transform:'translate(0px, -250px)',
				MozTransform:'translate(0px, -250px)',
				WebkitTransform:'translate(0px, -250px)',
				OTransform:'translate(0px, -250px)',
				MsTransform:'translate(0px, -250px)',
				width:230,
				height:230,
				marginLeft:0,
				marginTop:0
			};

			return i
		}.bind(this));

		this.counter=this.counter>=5?1:this.counter+1;

		return listArray
	}
	distance (point1, point2) {
		var a2 = Math.pow(Math.abs(point1[0] - point2[0]), 2);
		var b2 = Math.pow(Math.abs(point1[1] - point2[1]), 2);
		return Math.round(Math.sqrt(a2 + b2));
	}
	getViewportCenter (x,y) {
		return [x*250 + 125, y*250 + 125];
	}
	close (){
		clearTimeout(this.timer);
		this.timer=null;
		location.hash='#home';
		screenfull && screenfull.exit();
	}
	render (){
		var {app, wallMode, wallBackground, wallColor, isPhone, hasLogo} = this.props,
			listArray=this.state.listArray,
			colNum=$('#main')&&!isPhone?Math.round($('#main').width()/250):1,
			Plan=typeof plan!='undefined'?plan:null,
			isHideLogo=(Plan && Plan.features) ? Plan.features.is_hide_parllay_logo : false;

		return (
			<div className="main giant_screen giant_gem_screen" ref="giant_gem_screen" onClick={this.close.bind(this)} style={{backgroundColor:wallBackground}}>
				<div ref='temp' style={{position:'fixed',right:10,top:10,zIndex:10000,fontSize:'20px'}}></div>
				<div id="main">
					{listArray.map(function(i,index){
						var position={
							l:index%colNum*250+10,
							t:parseInt(index/colNum)*250+10
						}
						return <MainListGemItem key={index} isPhone={isPhone} position={position} model={i} index={index} wallColor={wallColor} wallMode={wallMode} />
					})}
				</div>
				{hasLogo?<img className="parllay_logo" src={!isHideLogo?"/dashboard/images/sign-in-logo.png":wallLogo} />:''}
			</div>
		)
	}
};

/*扑克牌动画*/
class PokerList extends React.Component {
	constructor (props){
		super();
		var data=props.data;

		this.pokerPadding = 70;
		this.loaded = 0;
		this.isAnimating = false;
		this.timer = null;

		this.initialize();
		this.currentAnimationItem=data.length>1?-1:0;
		this.state = {
			data:data
		}
	}
	shouldComponentUpdate (nextProps, nextState){
		return !this.isPokerMounted && !nextProps
	}
	componentDidMount (){

	}
	componentDidUpdate (){
		if(this.isPokerMounted){
			if(this.currentAnimationItem<=this.getItemLength()){
				this.animateStart()
			}else{
				this.animateStop()
			}
		}
	}
	componentWillUnmount (){
		//document.getElementById('wrapper').style.overflow=null
	}
	initialize (){
		//document.getElementById('wrapper').style.overflow='hidden'
	}
	onLoaded (e){
		var	datalength=this.getItemLength();

		this.setItemRatio(e);

		if(++this.loaded == datalength){
			this.isPokerMounted=true;
			this.forceUpdate()
		}
	}
	setItemRatio (e){
		var self=this,
			data=this.state.data,
			data=_.map(data,function(i){
				if(!i.ratio && (e.target.src.indexOf(i.isVideo?i.poster:i.photo_url)>=0)){
					i.ratio=(e.target.offsetHeight/e.target.offsetWidth).toFixed(2)
				}
				i.rotate=self.getItemRotation();
				i.zIndex=self.getItemZindex();

				return i
			});

		this.setState({
			data:data
		})
	}
	getItemLength (){
		var data=this.state.data;

		return data.length
	}
	getExpectItemWidth (isFill){
		var container=this.refs.container,
			padding=this.pokerPadding,
			width=container.offsetWidth-padding*2,
			height=container.offsetHeight-padding*2,
			pixel=width*height,
			datalength=this.getItemLength(),
			widthPerItem=_.min([Math.sqrt(pixel/datalength),350]);

		if(isFill){
			var colLength=Math.floor(width/widthPerItem),
				gap=(width-colLength*widthPerItem)/colLength;

			return {
				itemWidth:(widthPerItem+gap),
				colLength:colLength
			}
		}

		return widthPerItem
	}
	getItemZindex (){ 
		return Math.floor((Math.random()*5) + 1)
	}
    getItemRotation (){
    	var thumbRotation=45,
        	min = -1 * thumbRotation,
        	max = thumbRotation,
        	randomRotation = 'rotate(' + (Math.floor( Math.random() * (max - min + 1)) + min)+ 'deg)';

        return randomRotation
    }
	getItems (){
		var self=this,
			data=this.state.data;

		if(this.isPokerMounted){
			var positions=this.waterFallLayout(),
				container=this.refs.container,
				padding=this.pokerPadding,
				width=container.offsetWidth-padding*2,
				height=container.offsetHeight-padding*2,
				windowRatio=(height/width).toFixed(2);

			return data.map(function(i,index){
				var rotate=i.rotate,
					ratio=i.ratio,
					isThin=ratio>windowRatio,
					style=_.extend(positions[index],{
						position:'absolute',
						transform:rotate,
						MozTransform:rotate,
						WebkitTransform:rotate,
						OTransform:rotate,
						MsTransform:rotate,
						transitionDuration:'0.5s',
						MozTransitionDuration:'0.5s',
						WebkitTransitionDuration:'0.5s',
						OTransitionDuration:'0.5s',
						MsTransitionDuration:'0.5s',
						zIndex:i.zIndex,
						opacity:1
					});

				if((self.isAnimating && self.currentAnimationItem==index) || self.getItemLength()==1){
					style=_.extend(style,{
						width:isThin?height/ratio:width,
						height:isThin?height:width*ratio,
						left:isThin?'50%':0,
						top:isThin?0:'50%',
						transform:null,
						MozTransform:null,
						WebkitTransform:null,
						OTransform:null,
						MsTransform:null,
						zIndex:10000,
						marginLeft:isThin?-(height/ratio)/2:null,
						marginTop:isThin?null:-(width*ratio)/2
					})
				}

				if(self.currentAnimationItem>=self.getItemLength()){
					style=_.extend(style,{
						left:0,
						top:0,
						opacity:0
					})
				}

				return <PokerItem key={index} data={i} style={style} />
			})
		}else{
			return data.map(function(i,index){
				var rotate=self.getItemRotation();

				var style={
					position:'absolute',
					left:0,
					top:0,
					opacity:0
				};

				return <PokerItem key={index} data={i} style={style} onLoad={self.onLoaded.bind(self)} />
			})
		}
	}
	waterFallLayout (){
		var self=this,
			data=this.state.data,
			expectItem=this.getExpectItemWidth(true),
			itemWidth=expectItem.itemWidth,
			colLength=expectItem.colLength,
			tempArr=[],
			resultArr=[];

		data.forEach(function(i,index){
			var position=null;

			var col=tempArr.length!=colLength?index:_.indexOf(tempArr,_.min(tempArr)),
				t=tempArr[col] || -25;

			position={
				width:itemWidth,
				height:itemWidth*i.ratio,
				left:col*itemWidth,
				top:t
			}
			tempArr[col]=t+i.ratio*itemWidth-25;

			resultArr.push(position)
		});

		return resultArr
	}
	animateStart (){
		var self=this;
		
		this.isAnimating=true;

		this.clearTimer();

		this.timer=setTimeout(function(){
			self.currentAnimationItem++;
			self.forceUpdate()
		},this.currentAnimationItem>=this.getItemLength()?1000:3000)
	}
	animateStop (){
		var callback=this.props.callback;

		this.clearTimer();

		if(callback){
			setTimeout(callback,0)
		}
	}
	clearTimer (){
		if(this.timer){
			clearTimeout(this.timer);
			this.timer=null
		}
	}
	render (){

		return (
			<div className="poker-wrapper" ref="container" style={{padding:this.pokerPadding}}>
				<div className="poker-overlay"></div>
				<div className="poker-list">
					{this.getItems()}
				</div>
			</div>
		)
	}
};

class PokerItem extends React.Component {
	render (){
		var {data, style, onLoad} = this.props,
			isFocus=style.zIndex==10000;

		return (
			<div className={isFocus?"poker-item poker-item-focus":"poker-item"} style={style}>
				<img src={data.isVideo?data.poster:data.photo_url} onLoad={onLoad} />
				<p>
					<img src={data.user.profile_image || '/images/default.png'} />
					{data.description}
				</p>
			</div>
		)
	}
};

/*多屏设置*/
class MixtureSetting extends React.Component {
	constructor (){
		super();

		this.colorList = ['#333333','#7f7f7f','#c3c3c3','#f3f3f3','#ffffff','#8b0018','#f3152b','#ff7d3b','#fff14f','#00b159','#00a3e3','#434bc5','#a74a9f','#bc795c','#ffaec8','#ffc844','#efe4b5','#b0e54f','#95d9e8','#6f93bb','#c9bfe4']
	}
	chooseMode (mode){
		this.props.wrapper.setState({
			mixtureMode:mode
		})
	}
	chooseBackground (color){
		this.props.wrapper.setState({
			mixtureBackground:color
		})
	}
	chooseTextColor (color){
		this.props.wrapper.setState({
			mixtureColor:color
		})
	}
	chooseSpeed (speed){
		this.props.wrapper.setState({
			mixtureSpeed:speed
		})
	}
	componentDidMount (){
		//$(this.refs.firstTab).focus()
	}
	fullscreen (){
		var wrapper = this.props.wrapper.state,
			mode = wrapper.mixtureMode,
			color = wrapper.mixtureColor,
			bgColor = wrapper.mixtureBackground,
			speed = wrapper.mixtureSpeed;

		$.ajax({
			type:'post',
			url:'/walls/'+wallId+'/settings',
			data:{
				template:mode,
				type:'split',
				color:color,
				bgColor:bgColor,
				speed:speed
			}
		});

		screenfull && screenfull.request()
	}
	render (){
		var self=this,
			{title, mixtureMode, mixtureBackground, mixtureColor, mixtureSpeed, speedList} = this.props,
			colorList=this.colorList,
			modeSwatches=[];

		for(var i in mixtureControllers){
			(function(i){
				var mode=mixtureControllers[i];
				modeSwatches.push(<a key={i} href="javascript:void(0)" className={mixtureMode==i?"swatch swatch_selected mixture_screen "+mode.className:"swatch mixture_screen "+mode.className} onClick={function(){self.chooseMode(i)}}>{mode.screens.map(function(screen,index){
					return <div key={index}>{screen.name}</div>
				})}</a>)
			})(i)
		}

		return (
			<div className="weui_dialog_alert">
			    <div className="weui_mask"></div>
			    <div className="weui_dialog weui_dialog_confirm setting">
			        <div className="weui_dialog_hd weui_dialog_maintitle"><strong className="weui_dialog_title">{title}</strong></div>
			        <div className="weui_dialog_bd">
			        	<div className="swatches">
			        		{modeSwatches}
			        	</div>
			        </div>
			        <div className="weui_dialog_hd weui_dialog_subtitle"><strong className="weui_dialog_title">{i18next.t('play_mode.model_general.playback_speed')}</strong></div>
			        <div className="weui_dialog_bd">
			        	<div className="swatches">
			        		{speedList.map(function(i,index){
			        			return (
			        				<a key={index} href="javascript:void(0)" className={mixtureSpeed==index?"swatch swatch_small swatch_selected":"swatch swatch_small"} onClick={function(){self.chooseSpeed(index)}}>{i.name}</a>
			        			)
			        		})}
			        	</div>
			        </div>
			        <div className="weui_dialog_hd weui_dialog_subtitle"><strong className="weui_dialog_title">{i18next.t('play_mode.model_general.background_color')}</strong></div>
			        <div className="weui_dialog_bd">
			        	<div className="swatches">
			        		<div className="swatch swatch_small swatch_default" style={{backgroundColor:mixtureBackground}}></div>
			        		<span></span>
			        		{colorList.map(function(i,index){
			        			return (
			        				<a key={index} href="javascript:void(0)" className="swatch swatch_small" style={{backgroundColor:i}} onClick={function(){self.chooseBackground(i)}}></a>
			        			)
			        		})}
			        	</div>
			        </div>
			        <div className="weui_dialog_hd weui_dialog_subtitle"><strong className="weui_dialog_title">{i18next.t('play_mode.model_general.text_color')}</strong></div>
			        <div className="weui_dialog_bd">
			        	<div className="swatches">
			        		<div className="swatch swatch_small swatch_default" style={{backgroundColor:mixtureColor}}></div>
			        		<span></span>
			        		{colorList.map(function(i,index){
			        			return (
			        				<a key={index} href="javascript:void(0)" className="swatch swatch_small" style={{backgroundColor:i}} onClick={function(){self.chooseTextColor(i)}}></a>
			        			)
			        		})}
			        	</div>
			        </div>
			        <div className="weui_dialog_ft">
			        	<a href="#home" className="weui_btn_dialog default">{i18next.t('play_mode.model_general.cancel')}</a>
			            <a href="#mixture-player" onClick={this.fullscreen.bind(this)} className="weui_btn_dialog primary"><span className="glyphicon glyphicon-play-circle" style={{top:'2px'}}></span>{i18next.t('play_mode.model_general.play')}</a>
			        </div>
			    </div>
			</div>
		)
	}
};

/*大屏设置*/
class SliderSetting extends React.Component {
	constructor (){
		super();

		this.colorList = ['#333333','#7f7f7f','#c3c3c3','#f3f3f3','#ffffff','#8b0018','#f3152b','#ff7d3b','#fff14f','#00b159','#00a3e3','#434bc5','#a74a9f','#bc795c','#ffaec8','#ffc844','#efe4b5','#b0e54f','#95d9e8','#6f93bb','#c9bfe4']
	}
	chooseMode (mode){
		this.props.wrapper.setState({
			sliderMode:mode
		})
	}
	chooseBackground (color){
		this.props.wrapper.setState({
			sliderBackground:color
		})
	}
	chooseTextColor (color){
		this.props.wrapper.setState({
			sliderColor:color
		})
	}
	chooseSpeed (speed){
		this.props.wrapper.setState({
			sliderSpeed:speed
		})
	}
	componentDidMount (){
		//$(this.refs.firstTab).focus()
	}
	fullscreen (){
		var wrapper = this.props.wrapper.state,
			mode = wrapper.sliderMode,
			color = wrapper.sliderColor,
			bgColor = wrapper.sliderBackground,
			speed = wrapper.sliderSpeed;

		$.ajax({
			type:'post',
			url:'/walls/'+wallId+'/settings',
			data:{
				template:mode,
				type:'single',
				color:color,
				bgColor:bgColor,
				speed:speed
			}
		});

		screenfull && screenfull.request();
	}
	render (){
		var self=this,
			{title, sliderMode, sliderBackground, sliderColor, sliderSpeed, sliderSpeedList} = this.props,
			colorList=this.colorList;

		return (
			<div className="weui_dialog_alert">
			    <div className="weui_mask"></div>
			    <div className="weui_dialog weui_dialog_confirm setting">
			        <div className="weui_dialog_hd weui_dialog_maintitle"><strong className="weui_dialog_title">{title}</strong></div>
			        <div className="weui_dialog_bd">
			        	<div className="swatches">
			        		<a href="javascript:void(0)" className={sliderMode=='left-and-right'?"swatch swatch_selected":"swatch"} onClick={function(){self.chooseMode('left-and-right')}} ref="firstTab">{i18next.t('play_mode.screen_mode.or_so')}</a>
			        		<a href="javascript:void(0)" className={sliderMode=='classic-slides'?"swatch swatch_selected":"swatch"} onClick={function(){self.chooseMode('classic-slides')}}>{i18next.t('play_mode.screen_mode.big_picture')}</a>
			        		<a href="javascript:void(0)" className={sliderMode=='big-ball'?"swatch swatch_selected":"swatch"} onClick={function(){self.chooseMode('big-ball')}}>{i18next.t('play_mode.screen_mode.sphere')}</a>
			        	</div>
			        </div>
			        <div className="weui_dialog_hd weui_dialog_subtitle"><strong className="weui_dialog_title">{i18next.t('play_mode.model_general.playback_speed')}</strong></div>
			        <div className="weui_dialog_bd">
			        	<div className="swatches">
			        		{sliderSpeedList.map(function(i,index){
			        			return (
			        				<a key={index} href="javascript:void(0)" className={sliderSpeed==index?"swatch swatch_small swatch_selected":"swatch swatch_small"} onClick={function(){self.chooseSpeed(index)}}>{i.name}</a>
			        			)
			        		})}
			        	</div>
			        </div>
			        {sliderMode!='classic-slides'?<div className="weui_dialog_hd weui_dialog_subtitle"><strong className="weui_dialog_title">{i18next.t('play_mode.model_general.background_color')}</strong></div>:''}
			        {sliderMode!='classic-slides'?<div className="weui_dialog_bd">
			        	<div className="swatches">
			        		<div className="swatch swatch_small swatch_default" style={{backgroundColor:sliderBackground}}></div>
			        		<span></span>
			        		{colorList.map(function(i,index){
			        			return (
			        				<a key={index} href="javascript:void(0)" className="swatch swatch_small" style={{backgroundColor:i}} onClick={function(){self.chooseBackground(i)}}></a>
			        			)
			        		})}
			        	</div>
			        </div>:''}
			        <div className="weui_dialog_hd weui_dialog_subtitle"><strong className="weui_dialog_title">{i18next.t('play_mode.model_general.text_color')}</strong></div>
			        <div className="weui_dialog_bd">
			        	<div className="swatches">
			        		<div className="swatch swatch_small swatch_default" style={{backgroundColor:sliderColor}}></div>
			        		<span></span>
			        		{colorList.map(function(i,index){
			        			return (
			        				<a key={index} href="javascript:void(0)" className="swatch swatch_small" style={{backgroundColor:i}} onClick={function(){self.chooseTextColor(i)}}></a>
			        			)
			        		})}
			        	</div>
			        </div>
			        <div className="weui_dialog_ft">
			        	<a href="#home" className="weui_btn_dialog default">{i18next.t('play_mode.model_general.cancel')}</a>
			            <a href="#slider-player" onClick={this.fullscreen.bind(this)} className="weui_btn_dialog primary"><span className="glyphicon glyphicon-play-circle" style={{top:'2px'}}></span>{i18next.t('play_mode.model_general.play')}</a>
			        </div>
			    </div>
			</div>
		)
	}
};

/*瀑布流设置*/
class WallSetting extends React.Component {
	constructor (){
		super();

		this.colorList = [
			'#333333',
			'#7f7f7f',
			'#c3c3c3',
			'#f3f3f3',
			'#ffffff',
			'#8b0018',
			'#f3152b',
			'#ff7d3b',
			'#fff14f',
			'#00b159',
			'#00a3e3',
			'#434bc5',
			'#a74a9f',
			'#bc795c',
			'#ffaec8',
			'#ffc844',
			'#efe4b5',
			'#b0e54f',
			'#95d9e8',
			'#6f93bb',
			'#c9bfe4'
		]
	}
	chooseMode (mode){
		this.props.wrapper.setState({
			wallMode:mode
		})
	}
	chooseBackground (color){
		this.props.wrapper.setState({
			wallBackground:color
		});
		//$('#PCMenu').css('backgroundColor',color)
	}
	chooseTextColor (color){
		this.props.wrapper.setState({
			wallColor:color
		})
	}
	chooseSpeed (speed){
		this.props.wrapper.setState({
			wallSpeed:speed
		})
	}
	componentDidMount (){
		///$(this.refs.firstTab).focus()
	}
	fullscreen (){
		var wrapper = this.props.wrapper.state,
			mode = wrapper.wallMode,
			color = wrapper.wallColor,
			bgColor = wrapper.wallBackground,
			speed = wrapper.wallSpeed;

		$.ajax({
			type:'post',
			url:'/walls/'+wallId+'/settings',
			data:{
				template:mode,
				type:'multiple',
				color:color,
				bgColor:bgColor,
				speed:speed
			}
		});

		screenfull && screenfull.request();
	}
	render (){
		var self=this,
			{title, wallMode, wallBackground, wallColor, wallSpeed, wallSpeedList} = this.props,
			colorList=this.colorList;

		return (
			<div className="weui_dialog_alert">
			    <div className="weui_mask"></div>
			    <div className="weui_dialog weui_dialog_confirm setting">
			        <div className="weui_dialog_hd weui_dialog_maintitle"><strong className="weui_dialog_title">{title}</strong></div>
			        <div className="weui_dialog_bd">
			        	<div className="swatches">
			        		<a className={wallMode=='waterfall-with-text'?"swatch swatch_selected":"swatch"} href="javascript:void(0)" onClick={function(){self.chooseMode('waterfall-with-text')}} ref="firstTab">{i18next.t('play_mode.waterfall_flow.graphic')}</a>
			        		<a className={wallMode=='waterfall-without-text'?"swatch swatch_selected":"swatch"} href="javascript:void(0)" onClick={function(){self.chooseMode('waterfall-without-text')}}>{i18next.t('play_mode.waterfall_flow.picture')}</a>
			        		<a className={wallMode=='waterfall-of-grid'?"swatch swatch_selected":"swatch"} href="javascript:void(0)" onClick={function(){self.chooseMode('waterfall-of-grid')}}>{i18next.t('play_mode.waterfall_flow.network')}</a>
			        		<a className={wallMode=='dancing-pearl'?"swatch swatch_selected":"swatch"} href="javascript:void(0)" onClick={function(){self.chooseMode('dancing-pearl')}}>{i18next.t('play_mode.waterfall_flow.pearl')}</a>
			        		<a className={wallMode=='dancing-gem'?"swatch swatch_selected":"swatch"} href="javascript:void(0)" onClick={function(){self.chooseMode('dancing-gem')}}>{i18next.t('play_mode.waterfall_flow.gem')}</a>
			        	</div>
			        </div>
			        <div className="weui_dialog_hd weui_dialog_subtitle"><strong className="weui_dialog_title">{i18next.t('play_mode.model_general.playback_speed')}</strong></div>
			        <div className="weui_dialog_bd">
			        	<div className="swatches">
			        		{wallSpeedList.map(function(i,index){
			        			return (
			        				<a key={index} href="javascript:void(0)" className={wallSpeed==index?"swatch swatch_small swatch_selected":"swatch swatch_small"} onClick={function(){self.chooseSpeed(index)}}>{i.name}</a>
			        			)
			        		})}
			        	</div>
			        </div>
			        <div className="weui_dialog_hd weui_dialog_subtitle"><strong className="weui_dialog_title">{i18next.t('play_mode.model_general.background_color')}</strong></div>
			        <div className="weui_dialog_bd">
			        	<div className="swatches">
			        		<div className="swatch swatch_small swatch_default" style={{backgroundColor:wallBackground}}></div>
			        		<span></span>
			        		{colorList.map(function(i,index){
			        			return (
			        				<a key={index} href="javascript:void(0)" className="swatch swatch_small" style={{backgroundColor:i}} onClick={function(){self.chooseBackground(i)}}></a>
			        			)
			        		})}
			        	</div>
			        </div>
			        <div className="weui_dialog_hd weui_dialog_subtitle"><strong className="weui_dialog_title">{i18next.t('play_mode.model_general.text_color')}</strong></div>
			        <div className="weui_dialog_bd">
			        	<div className="swatches">
			        		<div className="swatch swatch_small swatch_default" style={{backgroundColor:wallColor}}></div>
			        		<span></span>
			        		{colorList.map(function(i,index){
			        			return (
			        				<a key={index} href="javascript:void(0)" className="swatch swatch_small" style={{backgroundColor:i}} onClick={function(){self.chooseTextColor(i)}}></a>
			        			)
			        		})}
			        	</div>
			        </div>
			        <div className="weui_dialog_ft">
			        	<a href="#home" className="weui_btn_dialog default">{i18next.t('play_mode.model_general.cancel')}</a>
			            <a href="#wall-player" onClick={this.fullscreen.bind(this)} className="weui_btn_dialog primary"> <span className="glyphicon glyphicon-play-circle" style={{top:'2px'}}></span>{i18next.t('play_mode.model_general.play')}</a>
			        </div>
			    </div>
			</div>
		)
	}
};

/*工具组件*/
/*上拉菜单*/
class ActionSheet extends React.Component {
	shouldComponentUpdate (nextProps, nextState){
		return this.props.actionSheet!=nextProps.actionSheet
	}
	close (){
		this.props.app.react.setState({
			actionSheet:false
		})
	}
	render (){
		var isOpen=this.props.actionSheet,
			list=isOpen?isOpen.list:[];

		return (
			<div id="actionSheet_wrap" style={{position:'relative',zIndex:1031}}>
			    <div className={isOpen?"weui_mask_transition weui_fade_toggle":"weui_mask_transition"} style={isOpen?{display:'block'}:{display:'none'}} id="mask"></div>
			    <div className={isOpen?"weui_actionsheet weui_actionsheet_toggle":"weui_actionsheet"} id="weui_actionsheet">
			        {list.map(function(i){
			        	return <div className="weui_actionsheet_menu">
				            {i.href?<a href={i.href} style={{display:'block'}} className="weui_actionsheet_cell">{i.name}</a>:<div onClick={i.callback} className="weui_actionsheet_cell">{i.name}</div>}
				        </div>
			        })}
			        <div className="weui_actionsheet_action">
			            <div className="weui_actionsheet_cell" id="actionsheet_cancel" onClick={this.close.bind(this)}>{i18next.t('play_mode.model_general.cancel')}</div>
			        </div>
			    </div>
			</div>
		)
	}
};

/*加载动画*/
class Loading extends React.Component {
	render (){
		return (
			<div className="weui_loading_toast">
			    <div className="weui_mask_transparent"></div>
			    <div className="weui_toast">
			        <div className="weui_loading">
			            <div className="weui_loading_leaf weui_loading_leaf_0"></div>
			            <div className="weui_loading_leaf weui_loading_leaf_1"></div>
			            <div className="weui_loading_leaf weui_loading_leaf_2"></div>
			            <div className="weui_loading_leaf weui_loading_leaf_3"></div>
			            <div className="weui_loading_leaf weui_loading_leaf_4"></div>
			            <div className="weui_loading_leaf weui_loading_leaf_5"></div>
			            <div className="weui_loading_leaf weui_loading_leaf_6"></div>
			            <div className="weui_loading_leaf weui_loading_leaf_7"></div>
			            <div className="weui_loading_leaf weui_loading_leaf_8"></div>
			            <div className="weui_loading_leaf weui_loading_leaf_9"></div>
			            <div className="weui_loading_leaf weui_loading_leaf_10"></div>
			            <div className="weui_loading_leaf weui_loading_leaf_11"></div>
			        </div>
			        <p className="weui_toast_content">{i18next.t('loading')}</p>
			    </div>
			</div>
		)
	}
};

/*确认对话框*/
class ConfirmDialog extends React.Component {
	shouldComponentUpdate (nextProps, nextState){
		return JSON.stringify(this.props.options)!=JSON.stringify(nextProps.options)
	}
	close (){
		var app=this.props.app,
			options=this.props.options;

		app.react.setState({
			confirmOptions:null
		});
		return options
	}
	cancel (){
		var options=this.close();

		if(options.cancel){
			options.cancel()
		}
	}
	confirm (){
		var options=this.close();

		if(options.confirm){
			options.confirm()
		}
	}
	render (){
		var options=this.props.options;

		return (
			<div>
				{options?<div>
				    <div className="weui_mask"></div>
				    <div className="weui_dialog">
				        <div className="weui_dialog_hd"><strong className="weui_dialog_title">{options.title || '确认对话框'}</strong></div>
				        <div className="weui_dialog_bd">{options.content}</div>
				        <div className="weui_dialog_ft">
				            <a href="javascript:void(0);" className="weui_btn_dialog default" onClick={this.cancel.bind(this)}>{i18next.t('play_mode.model_general.cancel')}</a>
				            <a href="javascript:void(0);" className="weui_btn_dialog primary" onClick={this.confirm.bind(this)}>{i18next.t('profile.wall.ok')}</a>
				        </div>
				    </div>
				</div>:''}
			</div>
		)
	}
};

/*app主体*/
class Wrapper extends React.Component {
	constructor (props){
		super();

		console.log(settings);
		var Settings=settings.template || {},
			settingType=Settings.type;
		

		this.sliderSpeedList = [
			{name: i18next.t('play_mode.model_general.fast') ,val:3333},
			{name: i18next.t('play_mode.model_general.centre') ,val:6666},
			{name: i18next.t('play_mode.model_general.slow') ,val:10000}
		];
		this.wallSpeedList = [
			{name: i18next.t('play_mode.model_general.fast') ,val:2},
			{name: i18next.t('play_mode.model_general.centre'),val:1},
			{name: i18next.t('play_mode.model_general.slow'),val:0.5}
		];
		this.state = {
			index:0,
			router:'mainList',
			mainCollection:props.app.mainCollection,
			pendingCollection:props.app.pendingCollection,
			approvedCollection:props.app.approvedCollection,
			rejectedCollection:props.app.rejectedCollection,
			deletedCollection:props.app.deletedCollection,
			hotCollection:props.app.hotCollection,
			setting:false,
			mixtureMode:settingType=='split'?Settings.template:'split-screen-1',
			mixtureBackground:'transparent',
			mixtureColor:'#333333',
			mixtureSpeed:1,
			sliderMode:settingType=='single'?Settings.template:'left-and-right',
			sliderBackground:'transparent',
			sliderColor:'#333333',
			sliderSpeed:1,
			wallMode:settingType=='multiple'?Settings.template:'waterfall-with-text',
			wallBackground:'transparent',
			wallColor:'#333333',
			wallSpeed:1,
			logo:wallLogo,
			mainTitle:wallName,
			describe:wallDescription,
			qrCode:wallQrcode,
			message:null,
			actionSheet:false,
			userPhotoCollection:[],
			userInfo:{},
			outlinkCollection:[],
			isPhone:props.isPhone,
			confirmOptions:null,
			isLoading:false,
			status:'pending',
			template:wallTemplate
		}
	}
	render (){
		var {
				setting,
				mixtureMode,
				mixtureBackground,
				mixtureColor,
				mixtureSpeed,
				sliderMode,
				sliderBackground,
				sliderColor,
				sliderSpeed,
				sliderSpeedList,
				wallMode,
				wallBackground,
				wallColor,
				wallSpeed,
				wallSpeedList,
				isLoading,
				isPhone
			} = this.state,
			app=this.props.app,
			sliderSpeedList=this.sliderSpeedList,
			wallSpeedList=this.wallSpeedList,
			settingHtml='';

		if(setting){
			var settingTitle=app.menuRouters[setting].title;

			switch(setting){
				case 'mixtureSetting':
					settingHtml=<MixtureSetting title={settingTitle} wrapper={this} mixtureMode={mixtureMode} mixtureBackground={mixtureBackground} mixtureColor={mixtureColor} mixtureSpeed={mixtureSpeed} speedList={sliderSpeedList} />
					break;
				case 'sliderSetting':
					settingHtml=<SliderSetting title={settingTitle} wrapper={this} sliderMode={sliderMode} sliderBackground={sliderBackground} sliderColor={sliderColor} sliderSpeed={sliderSpeed} sliderSpeedList={sliderSpeedList} />
					break;
				case 'wallSetting':
					settingHtml=<WallSetting title={settingTitle} wrapper={this} wallMode={wallMode} wallBackground={wallBackground} wallColor={wallColor} wallSpeed={wallSpeed} wallSpeedList={wallSpeedList} />
					break;
			}
		}

		return (
			<div className="wrapper">
				<ListTemplate wrapper={this}  />
				{settingHtml}
				{isLoading?<Loading />:''}
				{!isPhone?<LoadItemsWithoutSize collection={this.state.mainCollection} />:null}
			</div>
		)
	}
};

/*****************backbone 路由******************/

var AppRouter = Backbone.Router.extend({
	initialize:function () {
		this.isPhone=$(window).width()<768 && !isTV();

		if(this.isPhone){
			location.hash=''
		}

		moment.locale('en', {
		    relativeTime : {
		        past: i18next.t("variables.time.past"),
				m: i18next.t('variables.time.minute'),
				mm:i18next.t('variables.time.minutes'),
				h: i18next.t('variables.time.hour'),
				hh:i18next.t('variables.time.hours'),
				d: i18next.t('variables.time.day'),
				dd:i18next.t('variables.time.days'),
				M: i18next.t("variables.time.month"),
				MM:i18next.t("variables.time.months"),
				y: i18next.t('variables.time.year'),
				yy: i18next.t('variables.time.year')
		    }
		});

		/*collection1*/
		this.mainCollection=new CollectionList();
		this.mainCollection.comparator=this.descSort;
		this.mainCollection.on('all',function(type,item,list){
			this.react.setState({
				mainCollection:this.mainCollection
			})
		},this);

		/*collection2*/
		this.pendingCollection=new CollectionList();
		this.pendingCollection.comparator=this.descSort;
		this.pendingCollection.on('all',function(item,list){
			this.react.setState({
				pendingCollection:this.pendingCollection
			})
		},this);
		/*collection2.2*/
		this.approvedCollection=new CollectionList();
		this.approvedCollection.comparator=this.descSort;
		this.approvedCollection.on('all',function(item,list){
			this.react.setState({
				approvedCollection:this.approvedCollection
			})
		},this);
		/*collection2.3*/
		this.rejectedCollection=new CollectionList();
		this.rejectedCollection.comparator=this.descSort;
		this.rejectedCollection.on('all',function(item,list){
			this.react.setState({
				rejectedCollection:this.rejectedCollection
			})
		},this);
		/*collection2.4*/
		this.deletedCollection=new CollectionList();
		this.deletedCollection.comparator=this.descSort;
		this.deletedCollection.on('all',function(item,list){
			this.react.setState({
				deletedCollection:this.deletedCollection
			})
		},this);

		/*collection3*/
		this.hotCollection=new CollectionList();
		//this.hotCollection.comparator=this.descSort;
		this.hotCollection.on('all',function(item,list){
			this.react.setState({
				hotCollection:this.hotCollection
			})
		},this);

		/*config*/
		this.openId=true;
		this.isAnoymous=isAnoymous;
		this.isAdmin=isAdmin;

		this.react=ReactDOM.render(<Wrapper app={this} isPhone={this.isPhone} />,document.getElementById('wrapper'));

		this.bindTouchEvent();

		/*timer*/
		this.setRealtimePermission()

	},
	setRealtimePermission:function(){
		var self=this,
			Plan=typeof plan!='undefined'?plan:null,
			timer=is_realtime ? 30000 : ((Plan && Plan.features) ? Plan.features.screen_update_interval*1000 : 600000);

		setTimeout(function(){
			self.loadNew(null,function(data){
				if(is_realtime){
					var data=data?_.filter(data.data,function(i){ return i.type!='video'}):[];
					if(location.hash.indexOf('player')>=0  && data && data.length){
						ReactDOM.render(<PokerList data={data} callback={function(){
							ReactDOM.unmountComponentAtNode(document.getElementById('realtime'));
							self.setRealtimePermission()
						}} />,document.getElementById('realtime'))
					}else{
						self.setRealtimePermission()
					}
				}else{
					is_realtime=false;
					self.setRealtimePermission()
				}
			})
		},timer)
	},
	validateOpenId:function(){
		if(!this.openId){
			this.navigate('error',{trigger: true});
			return false
		}
		return true
	},
	routes:{
		'home':'mainList',
		'home-hot':'mainListHot',
		'photo':'uploadPhoto',
		'auditing/:id':'adminAuditing',
		'setting':'userSetting',
		'setname':'userSetname',
		'check-photos':'checkPhotos',
		'admin-setting':'adminSetting',
		'mixture-player':'mixturePlayer',
		'slider-player':'sliderPlayer',
		'wall-player':'wallPlayer',
		'mixture-setting':'mixtureSetting',
		'slider-setting':'sliderSetting',
		'wall-setting':'wallSetting',
		'outlink-list':'outlinkList',
		'error':'error',
		'*acts':'mainList'
	},
	menuRouters:{
		'mainList':{
			title: i18next.t('play_mode.more_screen_mode.photo_wall'),
			index:0
		},
		'mainListHot':{
			title: i18next.t('play_mode.more_screen_mode.photo_wall'),
			index:0
		},
		'uploadPhoto':{
			title: i18next.t('play_mode.more_screen_mode.upload_pictures'),
			index:1
		},
		'adminAuditing':{
			title: i18next.t('play_mode.more_screen_mode.administrative_approval'),
			index:2
		},
		'userSetting':{
			title: i18next.t('play_mode.more_screen_mode.user_settings'),
			index:3
		},
		'userSetname':{
			title: i18next.t('play_mode.more_screen_mode.set_nickname'),
			index:3
		},
		'checkPhotos':{
			title: i18next.t('play_mode.more_screen_mode.see_photos'),
			index:3
		},
		'adminSetting':{
			title: i18next.t('play_mode.more_screen_mode.administrator_settings'),
			index:3
		},
		'outlinkList':{
			title: i18next.t('play_mode.more_screen_mode.links_statistics'),
			index:3
		},
		'mixturePlayer':{
			title: i18next.t('play_mode.more_screen_mode.split_screen_play'),
			index:-1
		},
		'sliderPlayer':{
			title: i18next.t('play_mode.more_screen_mode.larger_broadcast'),
			index:-1
		},
		'wallPlayer':{
			title: i18next.t('play_mode.more_screen_mode.multiple_broadcast'),
			index:-1
		},
		'mixtureSetting':{
			title: i18next.t('play_mode.more_screen_mode.more_screen'),
			index:0
		},
		'sliderSetting':{
			title: i18next.t('play_mode.screen_mode.screen'),
			index:0
		},
		'wallSetting':{
			title: i18next.t('play_mode.waterfall_flow.waterfall'),
			index:0
		},
		'error':{
			title: i18next.t('play_mode.more_screen_mode.error'),
			index:-1
		}
	},
	mainList:function() {
		this.currentList='mainCollection';

		/*this.react.setState({
			router:'mainList'
		});*/

		if(!this.mainLoaded){
			this.mainListPage=0;
			this.loadMore();
			this.mainListStartTimestamp = Date.now();
			this.mainLoaded=true
		}else{
			this.loadNew('mainCollection')
		}
		this.clean()
	},
	mainListHot:function(){
		this.currentList='hotCollection';

		/*this.react.setState({
			router:'mainListHot'
		});*/

		if(!this.list3Loaded){
			this.mainListHot=0;
			this.loadMore();
			this.mainListHotStartTimestamp = Date.now();
			this.list3Loaded=true
		}else{
			this.loadMore()
		}
		this.clean(true)
	},
	uploadPhoto:function(){
		this.currentList='others';
		/*this.react.setState({
			router:'uploadPhoto'
		});*/
		this.clean()
	},
	adminAuditing:function(status){
		status=status=='approved'?'main':status;

		var collectionName=status+'Collection',
			isLoadBoo=status+'Loaded',
			pageCount=status+'ListPage',
			startTime = status+'StartTimestamp';

		this.currentList=collectionName;

		/*this.react.setState({
			router:'adminAuditing'
		});*/

		if(!this[isLoadBoo]){
			this[pageCount]=0;
			this.loadMore();
			this[startTime] = Date.now();
			this[isLoadBoo]=true
		}else{
			this.loadNew(collectionName)
		}
		this.clean()
	},
	userSetting:function(){
		this.currentList='others';
		/*this.react.setState({
			router:'userSetting'
		});*/
		this.clean()
	},
	userSetname:function(){
		this.currentList='others';
		/*this.react.setState({
			router:'userSetname'
		});*/
		this.clean()
	},
	checkPhotos:function(){
		this.currentList='others';
		/*this.react.setState({
			router:'checkPhotos'
		});*/
		this.clean()
	},
	adminSetting:function(){
		this.currentList='others';
		/*this.react.setState({
			router:'adminSetting'
		});*/
		this.clean()
	},
	outlinkList:function(){
		this.currentList='others';
		/*this.react.setState({
			router:'outlinkList'
		});*/
		this.clean()
	},
	mixturePlayer:function(){
		var self=this;
		this.currentList='mainCollection';

		(function loadMore(){
			if(!self.mainCollection.complete){
				self.loadMore('mainCollection',loadMore)
			}
		})()

		/*this.react.setState({
			router:'mixturePlayer'
		});*/

		this.clean(true)
	},
	sliderPlayer:function(){
		var self=this;
		this.currentList='mainCollection';

		(function loadMore(){
			if(!self.mainCollection.complete){
				self.loadMore('mainCollection',loadMore)
			}
		})()

		/*this.react.setState({
			router:'sliderPlayer'
		});*/

		this.clean(true)
	},
	wallPlayer:function(){
		var self=this;
		this.currentList='mainCollection';

		(function loadMore(){
			if(!self.mainCollection.complete){
				self.loadMore('mainCollection',loadMore)
			}
		})()

		/*this.react.setState({
			router:'wallPlayer'
		});*/

		this.clean(true)
	},
	mixtureSetting:function(){
		this.currentList='others';
		this.react.setState({
			setting:'mixtureSetting'
		});
		$('body').css('overflow','hidden')
	},
	sliderSetting:function(){
		this.currentList='others';
		this.react.setState({
			setting:'sliderSetting'
		});
		$('body').css('overflow','hidden')
	},
	wallSetting:function(){
		this.currentList='others';
		this.react.setState({
			setting:'wallSetting'
		});
		$('body').css('overflow','hidden')
	},
	error:function(){
		this.currentList='others';
		ReactDOM.unmountComponentAtNode(document.getElementById('menu'))(document.getElementById('menu'));
		this.menu=null;
		this.clean();
		var isError=$('#errorInfo').val();
		if(isError){
			alert(isError)
		}else{
			var url=encodeURIComponent('http://now-ppe.parllay.cn/router/index?url='+encodeURIComponent('http://'+window.location.host+window.location.pathname));
			window.location.href='https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxfd8db2900c3f9877&redirect_uri='+url+'&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect'
		}
	},
	clean:function (special) {
		document.documentElement.scrollTop = document.body.scrollTop =0;
		
		if(this.currentList!='others' && !special){
			if(!this[this.currentList].complete){
				if(window.specialScrollBinder){
					this.scrollContainer=specialScrollBinder(this.loadMore.bind(this))
				}else{
					this.scrollContainer=$(window).unbind('scroll').bind('scroll',function(){
						var scrollTop = $(window).scrollTop();
						var scrollHeight = $(document).height();
						var windowHeight = $(window).height();
						if(scrollTop + windowHeight>=scrollHeight-50){
							this.loadMore()
						}
					}.bind(this))
				}
			}else{
				if(this.scrollContainer){
					this.scrollContainer.unbind('scroll')
				}
			}
		}else{
			if(this.scrollContainer){
				this.scrollContainer.unbind('scroll')
			}
		}

		this.react.setState({
			setting:false
		});
		$('body').css('overflow','auto')
	},
	bindTouchEvent:function(){
		try{
			document.addEventListener('touchstart',this.touchStart.bind(this),false);
			document.addEventListener('touchmove',this.touchMove.bind(this),false);
			document.addEventListener('touchend',this.touchEnd.bind(this),false)
		}
		catch(e){

		}
	},
	yStart:0,
	yEnd:0,
	touchStart:function(e){
		if(this.currentList!='others'){
			try{
				var touch = e.touches[0];
				this.yStart=touch.pageY
			}
			catch(e){

			}
		}
	},
	touchMove:function(e){
		if(this.currentList!='others'){
			try{
				var touch = e.touches[0],
					offsetY=touch.pageY-this.yStart,
					offsetTop=$(window).scrollTop();
				
				/*if(offsetY>=0){
					this.react.setState({
						message:'松开加载更多'
					})
				}*/

				this.yEnd=touch.pageY
			}
			catch(e){

			}
		}
	},
	touchEnd:function(e){
		if(this.currentList!='others'){
			try{
				var offsetY=this.yEnd-this.yStart,
					offsetTop=$(window).scrollTop();
					console.log(offsetY);
				if(offsetY>=50 && offsetTop==0){
					this.loadNew()
				}else{
					this.react.setState({
						message:null
					})
				}

			}
			catch(e){
				console.log(e)
			}
		}
	},
	loadNew:function(special,callback){
		var self=this,
			isPhone=this.isPhone,
			pageSize = isPhone? 10: 20;
		//this.isLoading=true;
		//$('#loadingToast').show();
		console.log(this.currentList);
		switch(special || this.currentList){
			case 'mainCollection':
				loadMore(this.mainCollection,'/wall/',null,'mainList');
				break;
			case 'pendingCollection':
				loadMore(this.pendingCollection,'/wall/','pending','pending');
				break;
			case 'approvedCollection':
				loadMore(this.approvedCollection,'/wall/','approved&platform=console','approved');
				break;
			case 'rejectedCollection':
				loadMore(this.rejectedCollection,'/wall/','rejected&platform=console','rejected');
				break;
			case 'deletedCollection':
				loadMore(this.deletedCollection,'/wall/','deleted&platform=console','deleted');
				break;
			case 'hotCollection':
				loadMore(this.hotCollection,'/wall/','hot','mainListHot');
				break;
		}

		this.react.setState({
			message: i18next.t('loading')
		});

		function loadMore(collection,url,status,type){
			var startTime = self[type+'StartTimestamp'] || Date.now();
			var first= collection.length ? collection.at(0).get('timestamp') : startTime;
			$.ajax({
				url:url+wallId+'/photos?count='+ pageSize +'&type=new&since='+first+(status?'&status='+status:''),
				dataType:'json',
				success:function(data){
					if(data){
						if(data.success){
							if(data.data.length){
								collection.add(data.data,{merge: true})
							}
						}
					}
					if(callback){callback(data)}
					self.react.setState({
						message:null
					})
				},
				error:function(){
					if(callback){callback()}
					self.showLoading(false);
					$('#toast').show();
					setTimeout(function(){$('#toast').hide()},3000)
					self.react.setState({
						message:null
					})
				}
			});
			//self.isLoading=false;
		}
	},
	loadMore:function(special,callback){
		var self=this,
			isPhone=this.isPhone,
			pageSize = isPhone? 10: 20;

		if(this[special || this.currentList].complete){
			return
		}
		
		switch(special || this.currentList){
			case 'mainCollection':
				if(!this.mainLoading){
					this.mainLoading=true;
					loadMore(this.mainCollection,'/wall/','mainLoading')
				}
				break;
			case 'pendingCollection':
				if(!this.pendingLoading){
					this.pendingLoading=true;
					loadMore(this.pendingCollection,'/wall/','pendingLoading','pending')
				}
				break;
			case 'approvedCollection':
				if(!this.approvedLoading){
					this.approvedLoading=true;
					loadMore(this.approvedCollection,'/wall/','approvedLoading','approved&platform=console')
				}
				break;
			case 'rejectedCollection':
				if(!this.rejectedLoading){
					this.rejectedLoading=true;
					loadMore(this.rejectedCollection,'/wall/','rejectedLoading','rejected&platform=console')
				}
				break;
			case 'deletedCollection':
				if(!this.deletedLoading){
					this.deletedLoading=true;
					loadMore(this.deletedCollection,'/wall/','deletedLoading','deleted&platform=console')
				}
				break;
			case 'hotCollection':
				if(!this.hotLoading){
					this.hotLoading=true;
					loadMore(this.hotCollection,'/wall/','hotLoading',null,'hot')
				}
				break;
		}
		function loadMore(collection,url,loading,status,mode){

			if(!special){self.showLoading(true)}

			setTimeout(function(){
				/*if(!url.slice(8*(page+1),8*(page+2)).length){
					collection.complete=true
				}
				collection.add(url.slice(8*page,8*(page+1)));*/
				var isHot=mode=='hot',
					last= (collection.length && !isHot) ? collection.at(collection.length-1).get('timestamp') : Date.now();
				$.ajax({
					url:url+wallId+'/photos?count='+ pageSize +'&type=old&since='+last+(status?'&status='+status:'')+(mode?'&mode='+mode:''),
					dataType:'json',
					success:function(data){
						try{
							if(data){
								if(data.success){
									if(isHot){
										collection.reset(data.data)
									}else{
										if(data.data.length){
											collection.add(data.data,{merge: true});
											setTimeout(function(){
												if(callback){callback(data.data)}
											})
										}else{
											if(callback){callback()}
											if(!last && !status && !self.isAnoymous && canUpload){
												location.hash='photo'
											}
											collection.complete=true
										}
									}

									if(!special){self.showLoading(false)}
								}else{
									if(callback){callback()}
								}
							}else{
								if(callback){callback()}
							}
						}catch(e){
							if(callback){callback()}
							console.log(e.stack)
						}
					},
					error:function(){
						if(callback){callback()}
						self.showLoading(false);
						$('#toast').show();
						setTimeout(function(){$('#toast').hide()},3000)
					}
				});
				self[loading]=false;
			},1000)
		}
	},
	showLoading:function(boo){
		this.react.setState({
			isLoading:!!boo
		})
	},
	removeModel:function(c,id){
		var m=this[c].get(id);
		if(m){
			return this[c].remove(m)
		}
		return null
	},
	addMedel:function(c,m){
		this[c].add(m,{merge: true})
	},
	getNewTimestamp:function(c,m){
		var collection=this[c],
			first=collection.length?collection.at(0).get('timestamp'):Date.now(),
			last=collection.length?collection.at(collection.length-1).get('timestamp'):Date.now(),
			modelTimestamp=m.get('timestamp');

		if(modelTimestamp<last){
			return (last-1)
		}
		else if(modelTimestamp>first){
			return (first+1)
		}

		return modelTimestamp
	},
	descSort:function(m1,m2){
		return m2.get('timestamp')-m1.get('timestamp')
	}
});

$(function(){
	var app = new AppRouter;
	app.on('route',function(router,param){
		try{

			var self=this,
				index=this.menuRouters[router].index;

			if(this.menu){
				this.menu.setState({
					router:index
				})
			}
			if(this.react){
				var reactState={
					router:router
				};

				if(param[0]){
					reactState.status=param[0]
				}
				if(router.indexOf('Player')>=0){
					setTimeout(function(){
						self.react.setState(reactState)
					},500)
				}else{
					this.react.setState(reactState)
				}
				
			}

		}catch(err){
			alert(err.message);
			alert(err.stack);
		}
		//document.title=this.menuRouters[e].title
	});
	Backbone.history.start({
		beforeAction:function(){
			$('#loadingToast').hide()
		}
	});
	app.validateOpenId()
});

//alert(navigator.userAgent)
function isTV() {
    var userAgentInfo = navigator.userAgent;
    var Agents = ['Parllay']; //"Android", "iPhone","SymbianOS", "Windows Phone","iPad", "iPod"
    var flag = false;
    for (var v = 0; v < Agents.length; v++) {
        if (userAgentInfo.indexOf(Agents[v]) >= 0) {
            flag = true;
            break;
        }
    }
    return flag;
}

(function(a,b){"use strict";var c=function(){var a=[["requestFullscreen","exitFullscreen","fullscreenchange","fullscreen","fullscreenElement"],["webkitRequestFullScreen","webkitCancelFullScreen","webkitfullscreenchange","webkitIsFullScreen","webkitCurrentFullScreenElement"],["mozRequestFullScreen","mozCancelFullScreen","mozfullscreenchange","mozFullScreen","mozFullScreenElement"]];for(var c=0,d=a.length;c<d;c++){var e=a[c];if(e[1]in b)return e}}();if(!c)return a.screenfull=!1;var d="ALLOW_KEYBOARD_INPUT"in Element,e={init:function(){return b.addEventListener(c[2],function(a){e.isFullscreen=b[c[3]],e.element=b[c[4]],e.onchange(a)}),this},isFullscreen:b[c[3]],element:b[c[4]],request:function(a){a=a||b.documentElement,a[c[0]](d&&Element.ALLOW_KEYBOARD_INPUT),b.isFullscreen||a[c[0]]()},exit:function(){b[c[1]]()},toggle:function(a){this.isFullscreen?this.exit():this.request(a)},onchange:function(){}};a.screenfull=e.init()})(window,document)







